zoukankan      html  css  js  c++  java
  • GT考试

    f[i][j]表示准考证号前i位的后j位与不吉利串的前j位相等

    那么答案就是

    转移方程:

      

    a[i][j]表示不吉利串的第i位后加 从0~9之间的数之后变为不吉利串第j位的方案数

    求a[i][j] 用kmp

      大概意思就是:

      (1):先跑一遍kmp 把不吉利串的fail 都先求出来

      (2):for(i 0→m-1)

            for(p 0→9)

            求不吉利串前i位+p 的fail值

            其fail值即是第i位后加上p可以转移到的位数

     a[i][j] 是一个矩阵,f[i][j]也是一个矩阵(只取其中的lenm 段,相当于使其滚动起来)

                     ↓

     

    然后用矩阵快速幂

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #define ll long long
      5 using namespace std;
      6 
      7 int n,lenw,kk;
      8 char w[31];
      9 ll a[31][31];
     10 int fail[31];
     11 ll f[31][31];
     12 
     13 void kmp()
     14 {
     15     for(int i=2,j=0;i<=lenw;++i)
     16     {
     17         while(j&&w[i-1]!=w[j])
     18           j=fail[j];
     19         if(w[i-1]==w[j])
     20           fail[i]=++j;
     21     }
     22     for(int i=0;i<lenw;++i)
     23       for(int p=0;p<=9;++p)
     24       {
     25             int k=i;
     26             while(k&&w[k]!=p+'0')
     27               k=fail[k];
     28             if(w[k]==p+'0')
     29               ++k;
     30             ++a[i][k];
     31         }
     32         
     33     /*for(int i=0;i<=lenw;i++)
     34     {
     35         //printf("
    ");
     36         for(int j=0;j<=lenw;j++)
     37           printf("%d ",a[i][j]);
     38         printf("
    ");
     39     }*/
     40 }
     41 
     42 int temp[31][31];
     43 
     44 void out11()
     45 {
     46     printf("
    ");
     47     for(int i=0;i<=lenw;i++)
     48     {
     49         //printf("
    ");
     50         for(int j=0;j<=lenw;j++)
     51           printf("%d ",f[i][j]);
     52         printf("
    ");
     53     }
     54     printf("
    ");
     55     //printf("%d",ans);
     56 }
     57 
     58 int main(){
     59     //freopen("bzoj_1009.in","r",stdin);
     60     //freopen("bzoj_1009.out","w",stdout);
     61     scanf("%d%d%d%s",&n,&lenw,&kk,w);
     62     kmp();
     63     for(int i=0;i<=lenw;i++)
     64       f[i][i]=1;
     65     
     66     while(n)
     67     {
     68         if(n&1)
     69         {
     70             for(int i=0;i<=lenw;i++)
     71               for(int j=0;j<=lenw;j++)
     72               {
     73                     temp[i][j]=0;
     74                     for(int k=0;k<=lenw;k++)
     75                         temp[i][j]+=(f[i][k]*a[k][j])%kk;
     76                 }
     77             for(int i=0;i<=lenw;i++)
     78               for(int j=0;j<=lenw;j++)
     79                 f[i][j]=temp[i][j];
     80         }
     81         for(int i=0;i<=lenw;i++)
     82           for(int j=0;j<=lenw;j++)
     83           {
     84                 temp[i][j]=0;
     85                 for(int k=0;k<=lenw;k++)
     86                   temp[i][j]+=(a[i][k]*a[k][j])%kk;
     87             }
     88         for(int i=0;i<=lenw;i++)
     89           for(int j=0;j<=lenw;j++)
     90             a[i][j]=temp[i][j];
     91         n>>=1;
     92         //out11();
     93     }
     94     ll ans=0;//cout<<0;
     95     for(int i=0;i<lenw;i++)
     96     {
     97         ans+=f[0][i];
     98         ans%=kk;
     99     }
    100     printf("%lld",ans);
    101     //while(1);
    102     return 0;
    103 }
  • 相关阅读:
    20150826运算符,if语句
    20150825数据类型以及数据转换
    !!!SQL sever 函数表达
    SQL
    !!!遍历数组之多维数组!
    数组应用之————二分法查找
    数组-冒泡排列
    Homework!---判断多久过生日
    C#——语句!
    C#——语言基础 之 运算符!
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7225345.html
Copyright © 2011-2022 走看看