Loading

Codeforces 15xx 合集

CF1525

A. Potion-making

直接输出约分后的分母即可。

B. Permutation Sort

这玩意看起来就不用很多次,如果本来就是有序的那么就是 \(0\),如果 \(a_1=1\)\(a_n=n\) 那么显然只用 \(1\) 次。如果 \(a_n=1\)\(a_1=n\) 那么显然需要 \(3\) 次,否则 \(2\) 次即可。

C. Robot Collisions

容易发现这东西和国际象棋里黑白象是类似的,奇数位置的不会和偶数位置的相撞,那么只用考虑奇偶性相同的点。然后只用使用一个栈来维护向右的点,如果只有一个向左的点在 \((x,0)\),我们可以把其看成一个在 \((-x,0)\) 的向右的点。最后再处理剩下所有向右的点,两两配对即可。

D. Armchairs

贪心是不对的,可以找到反例。这个时候看到数据范围我们想到dp,设 \(f_i\) 代表前 \(i\) 部分的答案,那么显然有 \(f_i=min(f_j+w(j+1,i))\),其中必须满足所有 \(1\) 都被 \(0\) 匹配,而 \(0\) 可以多于。接下来考虑计算 \(w(j+1,i)\),可以贪心计算,把最后的 \(1\) 与最后的 \(0\) 匹配即可。

E. Assimilation IV

根据期望的线性性我们只用考虑每个点的期望次数,即其概率。正难则反,考虑出现不了的概率。把所有可以使其出现的城市找出来,每次可以选一段后缀,将可以选的位置数乘起来,剩下的随便选,于是就做完了。

F. Goblins And Gnomes

首先发现这是个最小链覆盖,而最小链覆盖等于点数-二分图最大匹配,那么我们就是想要匹配尽量小。我们可以进行的一次操作就是找到一个点,然后把这点删了。显然,我们需要找到一个匹配的公共点,而这个点是一定存在的,不然匹配会加一。这个点很好找,预处理出最大独立集,然后在补集里删一个就好。考虑删点顺序,其实就是每次删多少点。这个直接 dp 就好了,总的复杂度是 \(O(n^3)\)

CF1528

A. Parsa's Humongous Tree

仔细阅读样例解释,然后发现你会了。每个点只有可能取到区间的两个端点,于是直接dp即可。

B. Kavi on Pairing Duty

再次仔细阅读样例解释,发现只有两种可能。

  1. 若干段长度相同的线段平分。

  2. 若干条长度相同的线段镶嵌,然后中间部分构成子问题。

C. Trees of Tranquillity

容易发现答案是第一棵树从根到叶子这一条链的子集。于是考虑dfs的时候维护答案。考虑答案集合在第二棵树上的形态:如果把所有点搞在第二课树上建出虚树,那么一定是取所有叶子。于是维护虚树的叶子即可。发现每次加入只需判断是否存在一个点有祖先关系即可。

D. It's a bird! No, it's a plane! No, it's AaParsa!

观察发现这个答案不大,考虑直接跑dijkstra。如何处理等待?直接从 i 向 i+1 连一条长度为 1 的边。

E. Mashtali and Hagh Trees

首先思考什么情况是合法的,其实也就是一棵内向树、一棵外向树、一棵内向树+一条链+一棵外向树。外向树和内向树显然是双射,除了一条链的情况本质相同,所以我们只需要外向树计数即可,设 \(f_n\) 为最长链为 \(n\) 的外向树。先考虑二叉的情况,这个时候可以dp考虑。在 \(f_{n-1}\) 棵树中选 \(2\) 个的方案数直接可重集组合数,但是考虑到不一定要两棵树都是 \(n-1\),所以考虑容斥即可。还可以是一叉的情况,直接继承 \(f_{n-1}\) 即可。

求得 \(f_n\) 后,枚举链的长度,为了防止算重,强制链的两端都是三度点,设这样的方案是 \(g_n\),那么答案可以写成 \(\sum_{i=1}{n-2}\sum_{j=1}^{n-i-1}g_jg_{n-i-1}\),这个东西显然可以后缀和优化,可以 \(O(n)\) 求得。

code

F. AmShZ Farm

感觉这个翻译简化还不如不简化。

题解

CF1535

A Fair Playoff

最大值小于最小值就不行。

B Array Reodering

先将奇偶分开,偶前奇后。容易发现这样最小。

C Unstable String

直接模拟,不是 \(?\) 的放栈里,然后稍微讨论一下即可。

D Playoff Tournament

写棵线段树模拟然后你就发现不用写线段树。。。

E Gold Transfer

贪心从上往下取,然后倍增维护就好。

F String Distance

以后注意看到这种数据范围就像根号分治(类比虚树)。先把同一字符集的放在一组,我们发现答案最多为 \(2\),至少为 \(1\)。什么时候为 \(1\)?即两个串切掉 \(lcp,lcs\) 后有一个串是升序的。

考虑 \(n\) 很小,直接枚举两个串然后模拟这个过程即可,复杂度 \(O(n^2|s|)\)。如果 \(|s|\) 很小,枚举每个串的每个子串,考虑有没有一个串是将这部分子串排序后的结果。但是这样会算重,我们只需把排完序后最前或最后不变的区间去掉即可。复杂度玄学 \(O(n|s|^2\log{s})\),所以调一下根号分治的块长就好了。

代码写得非常暴力,好像后一部分复杂度是 \(O(n|s|^3\log{s})\)。但是冲就完事。

#include <bits/stdc++.h>
#define register re
#define pc putchar
#define gc getchar
#define mp make_pair
#define pb push_back
#define pf push_front
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace Standard_IO{
	template <typename T>
	void read(T &x) {
		T flag = 1;
		char ch = gc();
		for (; !isdigit(ch); ch = gc()) if (ch == '-') flag = -1;
		for (x = 0; isdigit(ch); ch = gc()) x = x * 10 + ch - '0';
		x *= flag;
	}
	template <typename T>
	void write(T x) {
		if (x > 9) write(x / 10);
		pc(x % 10 + '0');
	}
	template <typename T>
	void print(T x) {
		if (x < 0) pc('-'), x = -x;
		write(x); pc(' ');
	}
}using namespace Standard_IO;
string s[200005], t;
int n;
int len;
map<string, vector<string>> cla;
unordered_map<string, bool> mark;
int main() {
	read(n);
	for (int i = 1; i <= n; i++) {
		cin >> t;
		s[i] = t;
		sort(t.begin(), t.end());
		cla[t].pb(s[i]);
	}
	len = s[1].length();
	ll ans = 0, before = 0;
	for (auto jzyakioi : cla) {
		vector<string> now = jzyakioi.second;
		n = now.size();
		ans += 1ll * n * before * 1337;
		before += n;
		if (n <= len * 250) {
			for (int i = 0; i < n; i++) {
				for (int j = i + 1; j < n; j++) {
					int lcp = 0, lcs = 0;
					while (now[i][lcp] == now[j][lcp]) lcp++;
					while (now[i][len - lcs - 1] == now[j][len - lcs - 1]) lcs++;
					bool flag1 = 1, flag2 = 1;
					for (int k = lcp + 1; k < len - lcs; k++) {
						if (now[i][k] < now[i][k - 1]) {
							flag1 = 0;
						}
						if (now[j][k] < now[j][k - 1]) {
							flag2 = 0;
						}
					}
					ans += 2;
					if (flag1 || flag2) ans--;
				}
			}
		} else {
			ans += 1ll * n * (n - 1);
			mark.clear();
			for (auto x : now) mark[x] = true;
			for (auto x : now) {
				for (int i = 0; i < len; i++) {
					for (int j = i; j < len; j++) {
						string y = x;
						sort(y.begin() + i, y.begin() + j + 1);
						if (y[i] != x[i] && y[j] != x[j]) {//去重 
							if (mark[y]) {
								ans--;
							}
						}
					}
				}
			}
		}
	}
	print(ans);
	return 0;
}

CF1542

A. Odd Set

看奇数和偶数的数的个数相不相等即可。

B. Plus and Multiply

枚举所有 \(a^k\) 然后判断能不能加若干次 \(b\) 的到 \(n\)

C. Strange Function

\(g(i)=\text{lcm}(1,2,\dots,i)\),不难发现答案为 \(\sum_{}i\times(\lfloor\frac{n}{g(i-1)}\rfloor-\lfloor\frac{n}{g(i)}\rfloor)\)

D. Priority Queue

考虑对于每个 \(x\) 的贡献,首先他得被选中,记这次操作为 \(X\),然后还不能被删掉。考虑对这样的 \(B\) 计数。形式化讲就是被选中后遇到减号时小于 \(x\) 的数的个数得大于 \(0\)

考虑 \(dp\),记 \(f[i,j]\) 代表前 \(i\) 个操作有 \(j\) 个小于 \(x\) 的数的方案数(\(X\) 操作后,也就是说我们 dp 时是不包含操作 \(X\) 的。)。有如下转移:\(f[i,j]=f[i-1,j],f[i,(j-1,0)]=f[i-1,j](i<X),f[i,j-1]=f[i-1,j](i>X),f[i,j+1]=f[i-1,j](x_i<=x_X)\),注意遇到相同的时候加一个字典序就可以去重了。

E. Abnormal Permutation Pairs

思路来自神蛙。

\(f[i,j]\) 代表长度为 \(i\) 的两个排列逆序对之差为 \(j\) 的方案数。

由于这个 \(j\) 有可能是负数所以还需全部加上一个常数。

考虑从小到大枚举,有如下转移:

\[f[i,j]=f[i-1,k]\times\sum_{k_1=0}^{i}\sum_{k_2=0}^{i}[k_2-k_1=j-k] \]

我们发现这是一个背包。而背包可以用生成函数来表示。

形式化来讲,第 \(i\) 个数的生成函数即为

\[\sum_{j=0}^{i-1}x^j\sum_{j=0}^{i-1}x^{-j}=\frac{x^{i+1}+x^{-i+1}-2x}{(x-1)^2} \]

于是上面直接转移,再做两次回退即可。至于回退背包是什么,你可以看看这道题 消失之物

这一部分复杂度 \(O(n^3)\)

在算答案的时候先枚举公共前缀的长度,然后枚举不同的数是哪两个,然后所需逆序对数即知道了。复杂度 \(O(n^3)\)

CF1553

https://codeforces.com/contest/1553

A Digits Sum

统计 9 变成 10 的个数

B Reverse String

暴力模拟即可

C Penalty

暴力模拟即可

D Backspace

容易发现最后取完剩下一定是个偶数,然后中间每两个隔着的是奇数,且越晚取完越好,于是从后往前贪心即可

E Permutation Shift

对于一组排列我们从 \(a_i\to b_i\),然后数环的个数,设为 \(c\),最小 \(n-c\) 步。所以 \(n-c\le m\),所以 \(n-m\le c\),设自己到自己的数量是 \(k\),那么 \(c\le \frac{n+k}{2}\),所以 \(n-m\le \frac{n+k}{2}\)\(k\ge m\)。然后我们发现由于 \(m\le \frac{n}{3}\) 所以这样的排列最多就 \(3\) 个。于是我们就可以在 \(O(n)\) 的时间里求答案了。

这道题的思想就是不需要考虑全部情况,这在前几天的模拟赛里也遇到了同样的题。

F Pairwise Modulo

考虑增量构造,假设加入一个 \(b\)\(a\bmod b=a-[a/b]*b\),于是我们只用维护 \([a/b]\) 即可,直接枚举倍数,可以在 \(O(n\ln n)\) 里解决,在套一个树状数组,总复杂度 \(O(n\ln n\log n)\)

G Common Divisor Graph

通过奇偶分析发现答案最多为 2,所以预处理一下就好了。

H XOR and Distance

在trie树上暴力即可。

I Stairs

通过一些推导可以知道容斥后方案数至于长度有关,所以直接枚举长度即可。

CF1555

A. PizzaForces

容易发现这是几个勾股数,所以第一二种不会用很多,直接枚举用几个即可

B. Two Tables

答案只有可能在四个角,直接枚举

C. Coin Rows

枚举 A 在哪里下去,然后 B 要不直接下去,要不在最后一格才下去

D. Say No to Palindromes

回文串只用管长度为 2 和 3 的,而这等价于任意三个连续的位置不能有相同的字符,于是确定了前三个位置后面的字符都确定了,枚举然后前缀和预处理

E. Boring Segments

按 w 排序,枚举最小值,和最大值,也就是一段区间,显然右端点有单调性,直接尺取+线段树判断

F. Good Graph

容易发现这是个仙人掌,于是动态维护仙人掌,使用LCT维护圆方树即可。当然还可以离线+树剖

posted @ 2021-05-17 13:32  Gemini7X  阅读(46)  评论(0编辑  收藏  举报
Title