[BZOJ3576]江南樂
阿新 • • 發佈:2018-07-05
tchar amp 記憶 1-n include urn 想法 har 其中
挺好的題
我們算出每個數的sg值後異或起來即可
對於$n$,我們要求$sg_n$
樸素的想法是枚舉把$n$個石子分成$m$堆,有$m-n\%m$堆大小為$\left\lfloor\frac nm\right\rfloor$的石子,有$n\%m$堆大小為$\left\lfloor\frac nm\right\rfloor+1$的石子,因為是異或所以只有奇數堆的石子對$sg_n$有貢獻,直接算出來再求mex即可
考慮優化,暴力是枚舉$2\leq m\leq n$,因為當$\left\lfloor\frac nm\right\rfloor$相同時奇偶性相同的$m$算出來的答案是一樣的,所以我們只需枚舉所有使得$\left\lfloor\frac nm\right\rfloor$不同的$m$,用$m$和$m+1$更新答案即可
用記憶化搜索記錄答案即可,時間復雜度可能是$O\left(a\sqrt a\right)$,其中$a$是數字的大小
#include<stdio.h> #include<string.h> int f[100010],v[1000010],M,F; void get(int n){ if(~f[n])return; if(n<F){ f[n]=0; return; } int i,nex,s; for(i=2;i<=n;i=nex+1){ nex=n/(n/i); if(f[n/i]==-1)get(n/i); if(n!=2&&f[n/i+1]==-1)get(n/i+1); } M++; for(i=2;i<=n;i=nex+1){ nex=n/(n/i); s=0; if(n%i&1)s^=f[n/i+1]; if((i-n%i)&1)s^=f[n/i]; v[s]=M; if(i<nex){ s=0; if(n%(i+1)&1)s^=f[n/i+1]; if((i+1-n%(i+1))&1)s^=f[n/i]; v[s]=M; } } for(i=0;v[i]==M;i++); f[n]=i; } int main(){ int T,n,x,s; scanf("%d%d",&T,&F); memset(f,-1,sizeof(f)); while(T--){ scanf("%d",&n); s=0; while(n--){ scanf("%d",&x); get(x); s^=f[x]; } putchar(s?‘1‘:‘0‘); putchar(‘ ‘); } }
[BZOJ3576]江南樂