其他分享
首页 > 其他分享> > arc145

arc145

作者:互联网

\(\textbf{A.}\)

当 \(n = 2\) 时有解当且仅当 \(S _ 1 = S _ 2\). 下设 \(n \geq 3\).

设若干次操作 \(S\) 得到是回文串 \(T\). 则 \(T _ 1 \in \{ \texttt{A} , S _ 1 \}\), \(T _ n \in \{ \texttt{B}, S _ n \}\). 而 \(T _ 1 = T _ n\). 故 \((S _ 1, S _ n) \neq (\texttt{A}, \texttt{B})\).

下证这是充分的. 则必有 \(S _ 1 = \texttt{B}\) 或 \(S _ n = \texttt{A}\) 成立.

于是这个条件是充分的. 于是就做完了. 时间复杂度 \(\mathcal{O} (n)\).

void solve(){
	int n; cin >> n;
	string S; cin >> S; S = " " + S;
 
	if(n == 2){
		cout << (S[1] == S[2] ? "Yes" : "No") << "\n";
	}
	else{
		cout << (S[1] == 'B' || S[n] == 'A' ? "Yes" : "No") << "\n";
	}
}

\(\textbf{B}.\)

先考虑最开始有 \(m\) 堆石子的情况下, Alice 获胜的充要条件.

所以答案为:

所以就做完了. 时间复杂度 \(\mathcal{O}(1)\).

void solve(){
	ll n, a, b; cin >> n >> a >> b;
	if(n < a){
		cout << 0 << "\n";
	}
	else if(a <= b){
		cout << n - a + 1 << "\n";
	}
	else{
		cout << (n / a - 1) * b + min(b, n % a + 1) << "\n";
	}
}

\(\textbf{C.}\)

根据排序不等式, 有 \(M = \max ( \sum _ {i = 1} ^ {n} A _ i B _ i : \{ A _ 1, \cdots, A _ n \} \cup \{ B _ 1, \cdots, B _ n \} = \{ 1, \cdots, 2 n \} ) = \sum _ {i = 1} ^ {n} (2 i - 1) (2 i)\).

其中等号当且仅当 \(\{ A _ 1, B _ 1 \}, \cdots, \{ A _ n, B _ n \}\) 是 \(\{ 1, 2 \}, \cdots, \{ 2 n - 1, 2 n \}\) 的一个排列.

显然每个不同的排列对应的 \((P _ 1, \cdots, P _ {2n})\) 两两不同.

于是不妨设 \(\{ A _ 1, B _ 1 \} = \{ 1, 2 \}, \cdots, \{ A _ n, B _ n \} = \{ 2 n - 1, 2 n \}\), 之后方案数乘 \(n !\) 即可.

考虑分配 \((A _ 1, B _ 1) = (1, 2), \cdots, (A _ n, B _ n) = (2 n - 1, 2 n)\). 之后方案数乘 \(2 ^ n\) 即可.

看起来这样的方案数是 \(\dbinom{2 n}{n}\) 的.

但这样会算重. 例如 \((A _ 1, B _ 1) = (1, 2), P = (A _ 1, B _ 1)\) 和 \((A _ 1, B _ 1) = (2, 1), P = (B _ 1, A _ 1)\) 会同时计算上 \(P = (1, 2)\).

考虑人为钦定对于每个 \(1 \leq i \leq 2 n\), \((P _ 1, \cdots, P _ i)\) 中 \(A _ 1, \cdots, A _ n\) 的数的个数 $\geq $ \(B _ 1, \cdots, B _ n\) 的数的个数.

则将 \(P _ i = A _ *\) 的 \(i\) 看成左括号 \(\texttt{(}\); 将\(P _ i = B _ *\) 的 \(i\) 看成右括号 \(\texttt{)}\). 则上述条件等价于得到括号序列的是长度为 \(2 n\) 的合法括号序列. 这样的序列有 \(\mathrm{Catalan}(n) = \dfrac{1}{n + 1} \dbinom{2 n}{n}\) 个.

所以答案为 \(n ! \cdot 2 ^ n \cdot \mathrm{Catalan}(n)\). 直接计算即可. 时间复杂度 \(\mathcal{O}(n)\).

void solve(){
	int n; cin >> n;
	Binom binom(2 * n);
	cout << (modint(2).qpow(n) * binom.fact(n) * binom.catalan(n)).val() << "\n";
}

\(\textbf{D.}\)

先不考虑 \(\sum _ {s \in \mathcal{S}} s = m\) 的条件.

此时构造无穷(?)序列 \((a _ 0, \cdots, a _ n)\) 满足 \(a _ 0 = 0, a _ 1 = 1\), \(a _ i\) 是满足 \(x > a _ {i - 1}\) 且 \(\forall 0 \leq k < j < i\), 有 \(x \neq 2 a _ j - a _ k\) 的最小的正整数 \(x\).

手算 \(a\) 的前若干项为 \((0, 1, 3, 4, 9, 10, 12, 13, 27, 28, \cdots)\).

注意到设 \(i = (b _ t b _ {t - 1} \cdots b _ 0) _ 2\), 则 \(a _ i = \sum _ {i = 0} ^ {t} 3 ^ i b _ i = (b _ t b _ {t - 1} \cdots b _ 0) _ 3\). 同时记 \(t(i) = t\). 考虑证明这个序列是合法的.

考虑对 \(i + j + k\) 归纳证明 \(\forall 0 \leq k < j < i\) 有 \(a _ i + a _ k \neq 2 a _ j\).

事实上, 由 \(3 ^ n > 2 \cdot (1 + 3 + 9 + \cdots + 3 ^ {n - 1})\), 则若 \(a _ i = 2 a _ j - a _ k\), 则 \(t(i) = t(j)\). (否则若 \(t(i) > t(j)\), 则 \(a _ i \geq 3 ^ {t(i)} > 2 \cdot (1 + 3 + 9 + \cdots + 3 ^ {t(i) - 1}) \geq 2 \cdot (1 + 3 + 9 + \cdots + 3 ^ {t(j)}) \geq 2 a _ j\), 矛盾!)

所以 \(a _ {i - 2 ^ {t(i)}} = 2 a _ {j - 2 ^ {t(j)}} - a _ k\), 根据归纳假设出现矛盾!

所以取 \(\mathcal{S} = \{ a _ 1, \cdots, a _ n \}\) 符合条件.


现在考虑加上 \(\sum _ {s \in \mathcal{S}} s = m\) 的条件.

设上面构造的集合为 \(\mathcal{S} _ 0\). 设 \(m _ 0 = \sum _ {s \in \mathcal{S} _ 0} s\). 设 \(\Delta = m - m _ 0\), \(c = \left \lfloor \dfrac{\Delta}{n} \right \rfloor, d = \Delta \bmod {n}\).

则考虑取 \(\mathcal{S} = \{ a _ 1 + c + [1 \geq n - d + 1], \cdots, a _ n + c + [n \geq n - d + 1] \}\). 则 \(\sum _ {s \in \mathcal{S}} = m\).

但是这不一定符合条件. 因为虽然把差给扩大了, 但是扩大了不是一定就更优的. (例如 \(\{ 1, 3, 4 \} \to \{ 1, 3, 5 \}\) 反而不合法)

考虑用奇偶性修复这个锅. 从而我们取 \(\mathcal{S} = \{ 2 a _ 1 + c + [1 \geq n - d + 1], \cdots, 2 a _ n + c + [n \geq n - d + 1] \}\), 其中 \(\Delta = m - 2 \sum _ {s \in \mathcal{S} _ 0} s\).

设 \(e _ i = 2 a _ i + c + [i \geq n - d + 1]\), 则 \(\mathcal{S} = \{ e _ 1, \cdots, e _ n \}\) 且 \(e _ 1 < e _ 2 < \cdots < e _ n\).

则对于 \(1 \leq k < j < i \leq n\), 若 \(e _ i = 2 e _ j - e _ k\). 则 \(e _ 1, \cdots, e _ {n - d}\) 是奇数, \(e _ {n - d + 1}, \cdots, e _ n\) 是偶数.

注意到 \(e _ i, e _ k\) 同奇偶, 于是 \(1 \leq k < j < i \leq n - d\) 或 \(n - d + 1 \leq k < j < i \leq n\).

于是此时必有 \(a _ i = 2 a _ j - a _ k\). 这显然矛盾!

于是这个构造是合法的. 而 \(0 \leq a _ {n} \leq 1679697\), 所以得到的 \(e _ i\) 满足 \(|e _ i| \leq 10 ^ 7\), 这也就满足了题目的要求.

所以就做完了. 时间复杂度 \(\mathcal{O}(n \log n)\) 或 \(\mathcal{O}(n)\). (取决于是否精细实现 \(a _ i\) 的计算.)

void solve(){
	int n; ll S; cin >> n >> S;
 
	vector<int> basic(n + 1);
	basic[0] = 0;
	for(int i = 1; i <= n; i ++)
		basic[i] = 3 * basic[i / 2] + i % 2;
	for(int i = 1; i <= n; i ++)
		basic[i] *= 2;
 
	for(int i = 1; i <= n; i ++)
		S -= basic[i];
	ll rem = (S % n + n) % n, Delta = (S - rem) / n;
	vector<int> ans(n + 1);
	for(int i = 1; i <= n; i ++)
		ans[i] = basic[i] + Delta + (i >= n - rem + 1);
	for(int i = 1; i <= n; i ++)
		cout << ans[i] << " ";
	cout << "\n";
}

\(\textbf{E.}\)

注意到正向操作得到的序列 \(c\), 一定存在集合 \(I _ 1, \cdots, I _ n\), \(I _ i \in \{ 1, \cdots, i - 1 \}\). 且 \(c _ i = a _ i \oplus \bigoplus _ {j \in I _ i} a _ j\).

故若 \(\{ a _ 1, \cdots, a _ {i - 1} \}\) 不能线性表出 \(a _ i \oplus b _ i\), 则显然无解. 下证否则一定有解(不保证操作次数 \(\leq 70000\)).

设 \(b _ i = a _ i \oplus \bigoplus _ {j \in I _ i} a _ j\). 考虑对 \(n\) 归纳. 当 \(n = 1\) 时是显然的, 假设 \(1, \cdots, n - 1\) 是成立的.

所以结论成立. 但是直接按照这个顺序操作并不能满足操作次数 \(\leq 70000\) 的限制.

注意到 \(n \leq 1000\), \(\log V \leq 60\), 所以考虑一个操作次数 \(\leq n \log V + \mathcal{O}(n) + \mathcal{O}(\log V)\) 的构造.

考虑归纳操作, 依次让 \(a _ n \gets b _ n, \cdots, a _ 1 \gets b _ 1\). 每次的操作次数 \(\leq \log V + \mathcal{O}(1)\) 的构造.


倒序考虑操作.

则逆向操作变为选择 \(1 \leq k \leq n\), 让 \(b _ i ' \gets \bigoplus _ {j = 1} ^ {i} b _ j\), \(\forall 1 \leq i \leq k\) 成立. 目标为 \(b \gets a\).

考虑操作让 \(\bigoplus _ {i = 1} ^ {n} b _ i \gets a _ i\), 之后只需操作一次 \(k = n\) 可符合 \(b _ n \gets a _ n\).

考虑给 \(a _ 1, \cdots, a _ n, b _ 1, \cdots, b _ n\) 重新赋值.

设 \(b _ 1, \cdots, b _ n\) 的一个最小字典序线性基为 \(\mathcal{S} = b _ {i _ 1}, \cdots, b _ {i _ t}\). 其中 \(1 \leq i _ 1 < i _ 2 < \cdots < i _ t \leq n\).

则令 \(B _ {i _ 1} = 2 ^ 0, B _ {i _ 2} = 2 ^ 1, \cdots, B _ {i _ t} = 2 ^ {t - 1}\). 设序列 \(a, b\) 按照这样重赋值得到的序列为 \(A,B\). (因为 \(b _ {i _ 1}, \cdots, b _ {i _ t}\) 无关且 \(2 ^ 0, \cdots, 2 ^ {t - 1}\) 线性无关)

而注意到 \(a _ 1, \cdots, a _ n, b _ 1, \cdots, b _ n\) 均可由 \(\mathcal{S}\) 线性表出, 所以 \(A _ 1, \cdots, A _ n, B _ 1, \cdots, B _ n\) 也可由 \(\{ 1, 2, \cdots, 2 ^ {t - 1} \}\) 线性表出.

而 \(B _ 1, \cdots, B _ n\) 的二进制表示形如 \(({0000}, {\bf{0001}}, {000{*}}, {\bf{0010}}, {00{*}{*}}, {\bf{0100}}, {0{*}{*}{*}}, {\bf{1000}}, {{*}{*}{*}{*}})\), 其中加粗代表 \(i _ 1, \cdots, i _ t\), 不加粗代表若干个形如这样的数.

所以我们想让 \(x = a _ n \oplus \bigoplus _ {i = 1} ^ {n} b _ i \gets 0\). 这只需要重复如下操作若干遍:

于是每次的操作次数是 \(\leq \log V + 1\) 的, 于是这也就解决了题目. 时间复杂度是 \(\mathcal{O}(n ^ 2 \log V)\) 的, 因为每次逆向操作都需要暴力模拟一遍.

struct Basis{
private:
	vector<ull> x, y;
	int c = 0;

public:
	void clear(){
		x = y = vector<ull>(60, 0);
		c = 0;
	}
	bool insert(ull z){
		ull w = 0;
		for(int i = 60 - 1; i >= 0; i --)
			if((z >> i) & 1){
				if(x[i])
					z ^= x[i], w ^= y[i];
				else{
					for(int j = 0; j < i; j ++)
						if(x[j] && ((z >> j) & 1))
							z ^= x[j], w ^= y[j];
					c ++; w ^= (1ull << (c - 1));
					x[i] = z, y[i] = w;
					for(int j = 60 - 1; j > i; j --)
						if(x[j] && ((x[j] >> i) & 1))
							x[j] ^= x[i], y[j] ^= y[i];
					return true;
				}
			}
		return false;
	}

	ull query(ull z){
		ull w = 0;
		for(int i = 60 - 1; i >= 0; i --)
			if((z >> i) & 1){
				if(x[i])
					z ^= x[i], w ^= y[i];
				else
					return (ull)-1;
			}
		return w;
	}
} ;

void solve(){
	int n; cin >> n;
	vector<ull> a(n + 1);
	for(int i = 1; i <= n; i ++)
		cin >> a[i];
	vector<ull> b(n + 1);
	for(int i = 1; i <= n; i ++)
		cin >> b[i];

	/* 先判断是否无解 */
	Basis C;
	C.clear();
	for(int i = 1; i <= n; i ++){
		if(C.query(a[i] ^ b[i]) == (ull)-1){
			cout << "No" << "\n";
			return;
		}
		C.insert(a[i]);
	}

	vector<int> oper;
	auto operate = [&](int k) -> void {
		oper.emplace_back(k);
		for(int i = 2; i <= k; i ++)
			b[i] ^= b[i - 1];
	} ;

	/* 按照 i = n, ..., 2 的顺序操作使得 a[i] = b[i] */
	for(int i = n; i >= 2; i --){
		if(a[i] == b[i])
			continue;

		C.clear();
		vector<ull> keys;
		for(int j = 1; j <= i; j ++)
			if(C.insert(b[j]))
				keys.emplace_back(j);
		for(int j = 1; j <= i; j ++)
			a[j] = C.query(a[j]),
			b[j] = C.query(b[j]);

		for(int j = 1; j <= i; j ++)
			assert(a[j] != (ull)-1 && b[j] != (ull)-1);

		while(true){
			ull s = a[i];
			for(int j = 1; j <= i; j ++)
				s ^= b[j];

			if(!s)
				break;

			operate(keys[__lg(s)] + 1);
		}
		operate(i);
	}

	reverse(oper.begin(), oper.end());

	cout << "Yes" << "\n";
	cout << (int)oper.size() << "\n";
	for(int k : oper)
		cout << k << " ";
	cout << "\n";
}

\(\textbf{F.}\)

咕咕咕.

标签:geq,int,texttt,leq,cdots,arc145,mathcal
来源: https://www.cnblogs.com/zhangmj2008/p/arc145.html