[CF1848F] Vika and Wiki
shaber 题没想出来,紫砂了。
这种题的经典方法是考虑贡献,注意到顺着想贡献不容易我们倒过来想,设 \(f_{i,j}\) 表示 \(i\) 轮后 \(j\) 的大小,则 \(f_{i,j}=\operatorname{xor}\limits_{k\in [0,i]} \binom{i}{k}\bmod 2\ \times a_{(j+k)\bmod n}\)。
然后根据 [CTSC2017] 吉夫特 我们知道中间那个组合数有贡献当且仅当 \(k\) 是 \(i\) 的子集。
因为 \(n\) 是二的次幂,所以 \(f_{n,p}=0\)。于是上界卡到 \(n\)。
然后考虑高维前缀和,因为 \((j+k)\bmod n\) 很难处理,我们先考虑一个特殊的 \(0\),这个是简单的,然后考虑什么时候 \(x\) 可以成为答案。如果 \(x\) 时刻 \(f_{x,0}=0\) 且 \(\exist i\in (0,n),f_{x,i}\neq 0\),则 \(f_{x+i,0}\neq 0\),所以这个条件等价于 \(\forall i\in [x,+\infty),f_{i,0}=0\),然后我们知道这个答案上界是 \(n\) 所以倒着枚举即可。\(\mathcal O(n\log n)\)。
#include <bits/stdc++.h>
#define pb emplace_back
#define fir first
#define sec second
using i64 = long long;
const int maxn = 1 << 20;
int n, a[maxn];
int main() {
scanf("%d", &n);
for(int i = 0;i < n;++ i)
scanf("%d", &a[i]);
for(int i = 0;(1 << i) < n;++ i)
for(int j = 0;j < n;++ j)
if(j >> i & 1)
a[j] ^= a[j ^ (1 << i)];
for(int i = n - 1;~ i;-- i)
if(a[i]) return printf("%d\n", i + 1), 0;
puts("0");
return 0;
}
标签:bmod,long,CF1848F,考虑,define,neq
From: https://www.cnblogs.com/663B/p/17621418.html