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