【bzoj3576】 江南乐 sg函数+根号优化

来源:互联网 发布:淘宝vx是什么意思 编辑:程序博客网 时间:2024/04/28 19:28

本题是道好题,虽然比较水,但是确实算是sg函数的一种应用了,首先O(n^2)的暴力求sg函数就可以拿到70分,之后我们考虑对于每一堆x,我们枚举它能分成的堆数i,那么它一定会分成n%i个n/i+1和i-n%i个n/i的,而n/i只有根号n个取值,然后就可以用通常数论的思路来枚举这根号n个取值。对于n%i和i-n%i,我们只需要知道它们的奇偶性就可以了,所以我们只需要枚举前两个(因为如果有两种奇偶性,那么前两种必定不同(差不多就是这个意思)),然后就可以O(n sqrt(n))解决了。


#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>#define maxn 100010using namespace std;int sg[maxn];int T,F,n;int get_sg(int x){if (sg[x]!=-1) return sg[x];if (x<F) return sg[x]=0;bool vis[maxn];memset(vis,0,sizeof(vis));for (int i=2;i<=x;i=x/(x/i)+1)  for (int j=i;j<=min(i+1,x);j++)  {  int t=0;  if ((x%j)&1) t^=get_sg(x/j+1);  if ((j-(x%j))&1) t^=get_sg(x/j);  vis[t]=1;   } for (int i=0;;i++) if (!vis[i]) return sg[x]=i;}int main(){scanf("%d%d",&T,&F);memset(sg,-1,sizeof(sg));while (T--){scanf("%d",&n);int ans=0;for (int i=1;i<=n;i++){int x;scanf("%d",&x);ans^=get_sg(x);}if (ans) printf("1"); else printf("0");if (T) printf(" ");}printf("\n");return 0;}


0 0
原创粉丝点击