题面
题解
考虑一个完美串 (s) 应该满足什么性质。
若 (s) 中 (0) 和 (1) 数量相同,那么显然是 (01) 交错的。
否则不妨设 (1) 比 (0) 多,那么循环意义下一定有连续的 (11),不然 (1) 不可能比 (0) 多。
又由于有连续的 (11),那么就不能有连续的 (00),不然这个串就不是完美串。
考虑一个 (1) 比 (0) 多的完美串 (s),那么在循环意义下,(s) 可以被分割成若干段 (1),而且每段 (1) 之间恰好隔着一个 (0)。
从 (s) 的每段 (1) 中删去一个 (1) 得到一个新的字符串 (t),容易证明 (s) 是完美串当且仅当 (t) 是完美串。
(0) 比 (1) 多的情况同理。
那么假设 (s) 中有 (x) 个 (0),(y) 个 (1)。这个过程其实相当于 ((x,y) o(x-y,y)) 或 ((x,y) o (x,y-x)),也就是辗转相减的过程,而辗转相减可以优化成辗转相除。
如果我们枚举一开始长度为 (n) 的完美串 (s) 中有 (i) 个 (0),(n-i) 个 (1) 的话,其实我们是可以模拟这个辗转相除的过程的。也就是说,我们可以从最后的串倒推回来 (s) 长什么样。
那么我们一个一个把倒推回来的串 (s) 和题目给的串比较,看是否匹配就行了。
用 bitset
优化匹配可以做到 (O(dfrac{n^3}{w})) 的时间复杂度。
代码如下:
#include<bits/stdc++.h>
#define un unsigned
#define N 1050
using namespace std;
namespace modular
{
const int mod=1000000007;
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
}using namespace modular;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^'0');
ch=getchar();
}
return x*f;
}
const un int base=1145141;
int n,ans;
int a[N],b[N];
char s[N];
bitset<N>now,ss,vis;
int work(int x,int y,bool opt)
{
if(!y)
{
for(int i=1;i<=x;i++) a[i]=opt;
return x;
}
int t=x/y;
int d=work(y,x-y*t,opt^1);
int nn=y+x-y*t;
int cnt=0;
for(int i=1;i<=nn;i++)
{
if(a[i]!=opt)
for(int j=1;j<=t;j++)
b[++cnt]=opt;
b[++cnt]=a[i];
}
for(int i=1;i<=x+y;i++) a[i]=b[i];
return d;
}
void solve(int d)
{
now.reset();
for(int i=1;i<=n;i++)
if(a[i]) now.set(i);
if((now&vis)==ss) ans++;
for(int i=1;i<d;i++)
{
bool t=now[1];
now[1]=0;
now>>=1;
if(t) now.set(n);
if((now&vis)==ss) ans++;
}
}
int main()
{
scanf("%d%s",&n,s+1);
for(int i=1;i<=n;i++)
{
if(s[i]!='?')
{
ss.set(i,s[i]-'0');
vis.set(i,1);
}
}
for(int i=0;i<=n;i++)
{
int d;
if(i<n-i) d=work(n-i,i,1);
else d=work(i,n-i,0);
solve(n/d);
}
printf("%d
",ans);
return 0;
}
/*
4
?01?
*/
/*
10
??????????
*/