暴走的图灵机

334人阅读 评论(0) 收藏 举报
分类:

题目描述

这里写图片描述

做法

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[n]);
    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]);
    }
}
查看评论

【GDOI模拟】暴走的图灵机

Description你有l和r两个字符串,初始l=”0”,r=”1”,每轮操作定义如下。 将r变成原来的l+原来的r,这里的+表示将两个字符串连接起来 将l变成原来的l 给定一个长度为m的匹配...
  • doyouseeman
  • doyouseeman
  • 2016-04-09 23:53:50
  • 396

【GDOI2016模拟3.9】暴走的图灵机

Description现在你有两个字符串,l=’0’,r=’1’。每一次操作是把l=r,r=l’+r。l’表示操作前的l。求n次操作后,所得的l中含有多少个模式串S,个数%p。 n...
  • alan_cty
  • alan_cty
  • 2016-04-11 19:38:20
  • 317

暴走大事件,等你回归!

-
  • gdyht
  • gdyht
  • 2017-11-16 00:05:37
  • 195

从暴走漫画实例谈产品改版与效果衡量 | 诸葛io

引言 纳尼?!听说暴走王尼玛一次改版就能把App启动次数提升1.5倍,单次访问时长提升1.3倍,次日留存提高1.3倍……你坑我吧?!暴走漫画作为广大年轻受众喜闻乐见的知名动漫品牌,其影响力有目共睹,...
  • zhugeio2015
  • zhugeio2015
  • 2016-06-14 19:49:33
  • 644

图灵机的意义与思想内涵

图灵提出图灵机的模型并不是为了同时给出计算机的设计,它的意义我认为有如下几点: 1、 它证明了通用计算理论,肯定了计算机实现的可能性,同时它给出了计算机应有的主要架构;2、 图灵...
  • weixin_36583895
  • weixin_36583895
  • 2017-06-13 20:28:36
  • 2936

图灵机到C语言

图灵机与C语言属于C语言入门教程,主要包括以下主要内容 对图灵机的解释 图灵机到C语言 若干编程原则...
  • xuyuanjia02008
  • xuyuanjia02008
  • 2015-11-27 16:30:53
  • 784

图灵机的介绍

图灵机的组成 a.一条存储带 :双向无限延长,上有一个个小方格 ,每个小方格,可存储一个数字或字母b.一个控制器:可以存储当前自身的状态, 包含一个读写头,可以读,写,更改存储带...
  • u012412427
  • u012412427
  • 2015-04-09 12:10:44
  • 939

和姜咏江老师讨论图灵机与冯·诺伊曼机的区别

姜老师的博文: 《图灵与冯·诺伊曼的区别》 姜咏江 本文引用地址:http://blog.sciencenet.cn/blog-340399-860479.html  转载请注明来自科学网博客,并请注...
  • l7331014
  • l7331014
  • 2015-01-18 10:29:36
  • 1703

图灵机的演示ppt和软体示范

  • 2011年01月07日 21:15
  • 1003KB
  • 下载

计算复杂性学习1-单带图灵机模拟

上一篇对图灵机得一些基本概念做了一介绍,这一节主要来模拟图灵机的运行。 PAL(Palindrome)定义如下:对于任意的x∈{0,1}∗x \in \{0,1\}^*,如果xx是回文,则PAL等于...
  • u010392759
  • u010392759
  • 2016-05-02 00:39:46
  • 1453
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 39万+
    积分: 1万+
    排名: 1455
    最新评论
    文章分类