版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Joky_2002/article/details/81459469
题目链接
函数niubia
设
为第
位为白色的估价函数
显然有
然后有个显(hen)然(nan)发现的性质
当
时,有
为什么有这个结论呢,让我们来尝试证明一下
首先当
时,显然成立,因为
都等于
当 时, 与 相同意味着他们的 函数转移形式也相同,那么通过简单数学归纳法就能发现转移给他们的 值也相同,所以他们的 也相同(我也不知道我在说什么)
反正大概就是这样了。。。。
然后xjb分块一下就好了,复杂度是 的,但是常数小,所以完全过得去
代码:
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const int INF = 2147483647;
const int maxn = 100010;
const int crz = 100007;
struct data{
int id,val;
};
vector<data> ha[maxn];
int n,m,b,ans,tot;
int sg[maxn],L[maxn],R[maxn],vis[maxn];
int stk[maxn],top;
inline LL getint()
{
LL ret = 0,f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') ret = ret * 10 + c - '0',c = getchar();
return ret * f;
}
inline int find(int x)
{
int pos = x % crz;
for (int i = 0; i < ha[pos].size(); i++)
if (ha[pos][i].id == x)
return ha[pos][i].val;
}
inline void insert(int id,int val)
{
int pos = id % crz;
ha[pos].push_back((data){id,val});
}
inline void init()
{
for (int i = 1; i <= n; i = n / (n / i) + 1)
L[++tot] = i , R[tot] = n / (n / i);
for (int i = tot; i >= 1; i--)
{
vis[0] = i;
int l = L[i],r = R[i],sum = 0;
for (int j = 2 * l; j <= n; j = (n / (n / j) / l + 1) * l)
{
int cnt = n / (n / j) / l - (j - 1) / l;
vis[sum ^ find(n / j)] = i;
if (cnt & 1) sum ^= find(n / j);
}
for (int j = 0; j <= n; j++)
if (vis[j] != i) {sg[i] = j; break;}
insert(n / l,sg[i]);
}
}
int main()
{
#ifdef AMC
freopen("AMC1.txt","r",stdin);
#endif
n = getint();
init();
n = getint();
for (int i = 1; i <= n; i++)
{
ans = 0;
m = getint();
for (int j = 1; j <= m; j++)
{
int pos = getint();
int id = upper_bound(L + 1,L + tot + 1,pos) - L - 1;
ans ^= sg[id];
}
printf(ans ? "Yes\n" : "No\n");
}
return 0;
}
这种题考场上看到就直接打表好了。。