「PKUSC2018」神仙的游戏
由于day2在考场上错误的先开了T3,导致T2只打满了暴力。。。T1暴力都没打满。。。 最后T3虽然想出了正解却因为计算几何的某些细节不会处理而gg掉了(平时不学计算几何活该gg),只得了20分。。。
于是只有132分,被大众分虐暴QWQWQWQWQWQ
其实T2的正解只要想到了 最后一个部分分就差不多会做啦。。。。
由于一个1和0 位移差的绝对值的 所以约数的位移差 的border 都不可行,所以正着的[ s[i] == '1' ] 和 倒着的 [ s[i] == '0' ] 卷一下,就可以判断哪些位移是可行的(不考虑被倍数覆盖的),然后再一个调和级数考虑倍数覆盖就好啦。。。
至于卷积写个FFT就ojbk了,注意eps不要开太小。。。不然会gg
#include<cstdio> #include<cstdlib> #include<algorithm> #include<ctime> #include<iostream> #include<complex> #include<cmath> #include<cstring> #define ll long long #define D double #define E complex<double> using namespace std; const int maxn=1100005; const D eps=1e-6,pi=acos(-1); E a[maxn],b[maxn]; int r[maxn],l,N,n; char s[maxn]; bool v[maxn]; ll ans; inline bool isZ(E x){ return x.real()<=eps;} inline void build(){ for(int i=0;i<n;i++) if(s[i]=='1') a[i]=1; else if(s[i]=='0') b[n-1-i]=1; for(N=1;N<((n<<1)-1);N<<=1) l++; for(int i=0;i<N;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); } inline void FFT(E *c,int f){ for(int i=0;i<N;i++) if(i<r[i]) swap(c[i],c[r[i]]); for(int i=1;i<N;i<<=1){ E omega(cos(pi/i),sin(pi/i)*f); for(int P=i<<1,j=0;j<N;j+=P){ E now(1,0); for(int k=0;k<i;k++,now*=omega){ E x=c[j+k],y=c[j+k+i]*now; c[j+k]=x+y; c[j+k+i]=x-y; } } } if(f==-1) for(int i=0;i<N;i++) c[i]/=N; } inline void calc(){ ans=n*(ll)n; for(int i=1;i<n;i++) if(!isZ(a[n-1-i]+a[n-1+i])) v[i]=1; for(int i=1;i<n;i++){ bool flag=1; for(int j=i;j<n;j+=i) if(v[j]){ flag=0; break;} if(flag) ans^=(n-i)*(ll)(n-i); } } inline void solve(){ build(); FFT(a,1),FFT(b,1); for(int i=0;i<N;i++) a[i]*=b[i]; FFT(a,-1); calc(); } int main(){ // freopen("T2.in","r",stdin); // freopen("T2.out","w",stdout); scanf("%s",s),n=strlen(s); solve(); printf("%lld\n",ans); return 0; }
我爱学习,学习使我快乐