https://www.lydsy.com/JudgeOnline/problem.php?id=4035
考虑如果选择的限定不是白子,也可以选择黑子
容易发现和原先游戏是等价的(可以撤销别人的操作
此时对于每一个白子的贡献是独立的
可得\(sg[]\)
\[sg[x] = mex_{k=1}^{n/x}\left \{ sg[x] \;xor \;sg[2x] \;xor \;\dots \;sg[kx]\right \}\]
然后打表发现对于\(n/x\)相同的数
sg值是相同的
然后复杂度就是\(\mathcal O(\sqrt n \times \sqrt n) = \mathcal O(n)\) 听说常数很小
为什么我的写法有8倍常数啊
后来学习了一下fyy的写法开ofast过了...
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
#include <bits/stdc++.h>
#define fo(i, n) for(int i = 1; i <= (n); i ++)
#define out(x) cerr << #x << " = " << x << "\n"
#define type(x) __typeof((x).begin())
#define foreach(it, x) for(type(x) it = (x).begin(); it != (x).end(); ++ it)
using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
x = 0;char c = getchar(); bool f = 0;
for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
if(f) x = -x;
}
const int N = 3e5 + 233;
int vis[N];
int used[N], used_cnt = 0;
int st[N], up[N], top = 0, dp[2][N];
int n, T, K, m, q;
inline int getnum(int i, int j, int x) {
return up[j] / x - up[i] / x;
}
inline int cal(int x) {
return x > K ? dp[1][n / x] : dp[0][x];
}
inline void doit(void) {
for(int i = 1, last = 0; i <= n; i = last + 1) {
last = n / (n / i);
st[++ top] = i; up[top] = last;
}
K = sqrt(n);
for(int i = top; i >= 1; i --) {
int x = st[i];
used_cnt = 0;
vis[0] = 1; used[++ used_cnt] = 0;
int p = 0;
for(int j = x + x; j <= n; ) {
int xk = j;
int _t = n / (n / xk) / x * x;
int num = (_t - j) / x + 1;;
if(!num) continue;
int t = p ^ cal(xk);
// if(i == 1) cout << p << " " << t << " " << num << " " << j << "\n";
vis[t] = 1; used[++ used_cnt] = t;
if(num & 1) p = t;
j = _t + x;
}
int t = 0;
while(vis[t]) ++ t;
if(x > K) dp[1][n / x] = t;
else dp[0][x] = t;
for(int k = 1; k <= used_cnt; k ++)
vis[used[k]] = 0;
}
}
int sg[N];
inline void n2(void) {
for(int i = n; i >= 1; i --) {
memset(vis, 0, sizeof vis);
int t = 0;
for(int j = i; j <= n; j += i) {
vis[t ^= sg[j]] = 1;
}
t = 0;
while(vis[t]) ++ t;
sg[i] = t;
}
for(int i = 1; i <= n; i ++)
cout << sg[i] << " "; puts("");
}
main(void) {
read(n);
// n2();
doit();
// for(int i = 1; i <= n; i ++)
// cout << cal(i) << " "; puts("");
for(read(T); T --;) {
read(q);
int ans = 0;
for(int i = 1; i <= q; i ++) {
int x; read(x); ans ^= cal(x);
}
puts(!ans ? "No" : "Yes");
}
}