「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;
}

  

posted @ 2018-06-07 09:10  蒟蒻JHY  阅读(497)  评论(0编辑  收藏  举报