您的位置:首页 > 其它

暴走的图灵机

2016-04-11 14:03 363 查看

题目描述



做法

m代表T串的长度。

一个显然的做法是设g[i]表示i次操作后左手串所包含T串的个数。

则g[i]=g[i-2]+g[i-1]+c

其中c表示跨越中间线(即隔开i-2和i-1次操作后左手串的那条线)的所有串中T串的数量。

设f[i]表示i次操作后左手串的长度。

仔细观察发现,当f[i-2]和f[i-1]都不小于m后,c的循环节为2。

然后先暴力找到最早的id满足f[id]比2m-2大,然后矩阵乘法。

#include<cstdio>
#include<algorithm>
#include<stack>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long LL;
const int maxn=100+10,maxm=50000+10;
int f[maxn],g[maxn],next[maxm];
bool pre[maxn][maxm],suc[maxn][maxm],s[maxm],ss[maxm];
int i,j,k,l,t,n,m,p,ans,id,c1,c2;
stack<int> sta;
char ch;
struct matrix{
int a[5][5];
};
matrix operator *(matrix a,matrix b){
matrix c;
int i,j,k;
fo(i,0,4)
fo(j,0,4) c.a[i][j]=0;
fo(k,1,4)
fo(i,1,4)
fo(j,1,4)
c.a[i][j]=(c.a[i][j]+(LL)a.a[i][k]*b.a[k][j]%p)%p;
return c;
}
matrix a,dis,c,one,tt;
int kmp(bool *a,int n,bool *b,int m){
int ans=0,i,j;
j=0;
next[1]=0;
fo(i,2,m){
while (j&&b[j+1]!=b[i]) j=next[j];
if (b[j+1]==b[i]) j++;
next[i]=j;
}
j=0;
fo(i,1,n){
while (j&&b[j+1]!=a[i]) j=next[j];
if (b[j+1]==a[i]) j++;
if (j==m){
ans=(ans+1)%p;
j=next[j];
}
}
return ans;
}
matrix quicksortmi(matrix x,int y){
if (y==0) return one;
tt=quicksortmi(x,y/2);
tt=tt*tt;
if (y%2) tt=tt*x;
return tt;
}
int main(){
scanf("%d%d%d",&n,&m,&p);
ch=getchar();
while (ch!='0'&&ch!='1') ch=getchar();
s[1]=ch-'0';
fo(i,2,m){
ch=getchar();
s[i]=ch-'0';
}
f[0]=f[1]=1;
fo(i,2,n){
if (f[i-1]+f[i-2]>1000000) f[i]=1000000;else f[i]=f[i-1]+f[i-2];
if (f[i]>m*5) break;
}
pre[0][1]=suc[0][1]=0;
pre[1][1]=suc[1][1]=1;
if (m==1){
if (s[1]) g[1]=1%p;else g[0]=1%p;
}
fo(i,2,n){
g[i]=(g[i-2]+g[i-1])%p;
if (f[i-1]<m){
fo(j,1,f[i-2]) ss[j]=pre[i-2][j];
fo(j,1,f[i-1]) ss[f[i-2]+j]=pre[i-1][j];
g[i]=(g[i]+kmp(ss,f[i],s,m))%p;
fo(j,1,min(f[i],m-1)) pre[i][j]=ss[j];
t=0;
fo(j,max(f[i]-m+2,1),f[i]) suc[i][++t]=ss[j];
}
else if (f[i-2]<m){
fo(j,1,f[i-2]) ss[j]=pre[i-2][j];
fo(j,1,m-1) ss[f[i-2]+j]=pre[i-1][j];
g[i]=(g[i]+kmp(ss,f[i-2]+m-1,s,m))%p;
fo(j,1,m-1) pre[i][j]=ss[j];
fo(j,1,m-1) suc[i][j]=suc[i-1][j];
}
else{
fo(j,1,m-1) ss[j]=suc[i-2][j];
fo(j,1,m-1) ss[j+m-1]=pre[i-1][j];
g[i]=(g[i]+kmp(ss,2*m-2,s,m))%p;
fo(j,1,m-1) pre[i][j]=pre[i-2][j];
fo(j,1,m-1) suc[i][j]=suc[i-1][j];
id=i;
break;
}
}
if (id==n) printf("%d\n",g
);
else{
fo(i,1,m-1) ss[i]=suc[id-1][i];
fo(i,1,m-1) ss[i+m-1]=pre[id-2][i];
c1=kmp(ss,2*m-2,s,m);
fo(i,1,m-1) ss[i+m-1]=pre[id-1][i];
c2=kmp(ss,2*m-2,s,m);
a.a[1][1]=g[id-1];
a.a[1][2]=g[id];
a.a[1][3]=c1;
a.a[1][4]=c2;
fo(i,0,4) a.a[0][i]=0;
fo(i,2,4)
fo(j,0,4)
a.a[i][j]=0;
dis.a[1][1]=dis.a[2][1]=dis.a[3][1]=1;
dis.a[2][2]=2;
dis.a[1][2]=dis.a[3][2]=dis.a[4][2]=1;
dis.a[3][3]=dis.a[4][4]=1;
//dis.a[4][1]=dis.a[1][3]=dis.a[2][3]=dis.a[4][3]=dis.a[1][4]=dis.a[2][]
fo(i,1,4) one.a[i][i]=1;
/*c=a*quicksortmi(dis,(n-id)/2);
if ((n-id)%2) printf("%d\n",((c.a[1][1]+c.a[1][2])%p+c1)%p);else printf("%d\n",c.a[1][2]);*/
/*c=a*quicksortmi(dis,(n-id+1)/2);
if ((n-id)%2) printf("%d\n",c.a[1][1]);else printf("%d\n",c.a[1][2]);*/
/*fo(i,1,(n-id+1)/2) a=a*dis;
if ((n-id)%2) printf("%d\n",a.a[1][1]);else printf("%d\n",a.a[1][2]);*/
/*tt=one;
fo(i,1,(n-id+1)/2) tt=tt*dis;
c=a*tt;
if ((n-id)%2) printf("%d\n",c.a[1][1]);else printf("%d\n",c.a[1][2]);*/
l=(n-id+1)/2;
while (l){
sta.push(l%2);
l/=2;
}
tt=one;
while (!sta.empty()){
tt=tt*tt;
if (sta.top()==1) tt=tt*dis;
sta.pop();
}
c=a*tt;
if ((n-id)%2) printf("%d\n",c.a[1][1]);else printf("%d\n",c.a[1][2]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: