由于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;
}
来源:oschina
链接:https://my.oschina.net/u/4391746/blog/3945787