给定一个01?串,对所有len询问是否存在一种填法使存在长度为len的border。
首先有个套路的性质:对于一个长度为len的border,这个字符串一定有长度为n-len的循环节(最后可以不完整)。
逆推得到,如果有一个0位置和一个1位置之差为len,则所有len的因数k的n-k都不可能成为border。
先将b翻转,作差卷起来,然后$O(n\log n)$枚举倍数即可。
$A(x)=x^{n-1}A(\frac 1x)$是作差卷积的本质。
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
5 using namespace std;
6
7 const int N=3000010,mod=998244353,G=3;
8 int n,len,l,a[N],b[N],rev[N],lg[N];
9 char s[N];
10
11 int ksm(int a,int b){
12 int res=1;
13 for (; b; a=1ll*a*a%mod,b>>=1)
14 if (b & 1) res=1ll*res*a%mod;
15 return res;
16 }
17
18 void NTT(int a[],int n,int f){
19 for (int i=0; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
20 for (int i=1; i<n; i<<=1){
21 int wn=ksm(G,(f==1) ? (mod-1)/(i<<1) : (mod-1)-(mod-1)/(i<<1));
22 for (int p=i<<1,j=0; j<n; j+=p)
23 for (int w=1,k=0; k<i; k++,w=1ll*w*wn%mod){
24 int x=a[j+k],y=1ll*w*a[i+j+k]%mod;
25 a[j+k]=(x+y)%mod; a[i+j+k]=(x-y+mod)%mod;
26 }
27 }
28 if (f==1) return;
29 int inv=ksm(n,mod-2);
30 for (int i=0; i<n; i++) a[i]=1ll*a[i]*inv%mod;
31 }
32
33 int main(){
34 freopen("pkub.in","r",stdin);
35 freopen("pkub.out","w",stdout);
36 scanf("%s",s); n=strlen(s);
37 for (len=1; len<=(n<<1); len<<=1) l++;
38 for (int i=0; i<len; i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
39 for (int i=0; i<n; i++) a[i]=s[i]=='0',b[i]=s[n-i-1]=='1';
40 NTT(a,len,1); NTT(b,len,1);
41 for (int i=0; i<len; i++) a[i]=1ll*a[i]*b[i]%mod;
42 NTT(a,len,-1);
43 long long ans=1ll*n*n;
44 for (int i=1; i<n; i++){
45 int f=1;
46 for (int j=i; j<n; j+=i) if (a[n-j-1]|a[n+j-1]) { f=0; break; }
47 if (f) ans^=1ll*(n-i)*(n-i);
48 }
49 printf("%lld\n",ans);
50 return 0;
51 }
来源:https://www.cnblogs.com/HocRiser/p/9163705.html