ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

arc145

2022-09-07 10:00:08  阅读:125  来源: 互联网

标签:geq int texttt leq cdots arc145 mathcal


\(\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}\) 成立.

  • 若 \(S _ 1 = \texttt{B}\), 则依次操作下标 \((2, 3), (3, 4), \cdots, (n - 1, n)\) 的元素. 得到 \(T = \texttt{BAA} \cdots \texttt{AAB}\) 符合要求.
  • 若 \(S _ n = \texttt{A}\), 则依次操作下标 \((n - 2, n - 1), \cdots, (2, 3), (1, 2)\) 的元素. 得到 \(T = \texttt{ABB} \cdots \texttt{BBA}\) 符合要求.

于是这个条件是充分的. 于是就做完了. 时间复杂度 \(\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 获胜的充要条件.

  • 当 \(m < a\) 时, 显然此时 Alice 失败.
  • 当 \(m \geq a\) 时:
    • 当 \(a \leq b\) 时, Alice 第一次取 \(a \left \lfloor \dfrac{m}{a} \right \rfloor > 0\) 个石子, 剩余 \(m \bmod {a} < a \leq b\) 个石子, 显然此时 Bob 失败. 于是 Alice 获胜.
    • 当 \(a > b\) 时:
      • 若 \(m \bmod {a} < b\), 同上可知 Alice 获胜.
      • 若 \(m \bmod a \geq b\), 设 Alice 第一次取完剩余 \(k\) 个石子, 则 \(k \geq b\). 则 Bob 第一次取 \(b \left \lfloor \dfrac{k}{b} \right \rfloor > 0\)个石子, 剩余 \(k \bmod {b} < b < a\) 个石子, 显然此时 Alice 失败. 于是 Bob 获胜.

所以答案为:

  • 当 \(a \leq b\) 时答案为 \(\sum _ {m = 1} ^ {n} [m \geq a] = n - m + 1\).
  • 当 \(a > b\) 时答案为 \(\sum _ {m = 1} ^ {n} [m \geq a] [m \bmod a < b] = \left ( \left \lfloor \dfrac{n}{a} \right \rfloor - 1 \right ) b + \min (b, n \bmod a + 1)\).

所以就做完了. 时间复杂度 \(\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\) 是成立的.

  • 若 \(n - 1 \in I _ n\). 则正向操作 \(1, \cdots, n - 1\) 若干次使得 \(a _ {n - 1} \gets a _ {n - 1} \oplus \bigoplus _ {j \in I _ {n} - \{ n - 1 \}} a _ j\). 则正向操作 \(k = n\), 有 \(a _ n \gets a _ {n} \oplus \bigoplus _ {j \in I _ n} a _ j = b _ n\). 于是划归成 \(n - 1\) 的情况了.
  • 若 \(n - 1 \notin I _ n\), 则正向操作 \(k = n\), 有 \(a _ n \gets a _ n \oplus a _ {n - 1}\), 划归成 \(n - 1 \in I _ n\) 的情况.

所以结论成立. 但是直接按照这个顺序操作并不能满足操作次数 \(\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\). 这只需要重复如下操作若干遍:

  • 设 \(x\) 的最高位为 \(s\), 则逆向操作 \(k = b _ {i _ s} + 1\), 则会让 \(b _ {i _ s + 1}\) 的第 \(s\) 位取反, 于是会让 \(\bigoplus _ {i = 1} ^ {n} b _ i\) 的第 \(s\) 位取反, 从而让 \(x\) 的最高位为 \(s\).
  • 很关键的一点是这样一定不会影响已经操作过的更高位的数字, 因为 \(i _ 1 < i _ 2 < \cdots < i _ t\). 所以每次清除 \(x\) 的最高位一定是可行.

于是每次的操作次数是 \(\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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有