zoukankan      html  css  js  c++  java
  • [HNOI2008]GT考试

    Description

    阿申准备报名参加GT考试,准考证号为N位数 X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。他的不吉利数学A1A2...Am(0<=Ai& lt;=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为0

    Input

    第一行输入N,M,K.接下来一行输入M位的数。 100%数据N<=10^9,M<=20,K<=1000 40%数据N<=1000 10%数据N<=6

    Output

    阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.

    Sample Input

    4 3 100
    111

    Sample Output

    81
     
     
     
     
     
     
     神题碰上弱菜.....
    动态规划啊,但数据这么大怎么想得到是动态规划呢,太弱了......
    f[i][j]表示准考证前i位中后j位为不吉利的数字的前j位。
    转移方程:
        
     

     

    因此就可以使用矩阵乘法加速了!

    a[k][j]表示f[i-1][k]转为f[i][j]的方法数,这步可以用KMP解决。

    ans+=f[0][j] (j=0;j<m;++j);

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string.h>
     5 #include<fstream>
     6 using namespace std;
     7 //ifstream fin("fin.in");
     8 
     9 string s;
    10 int n,m,mod,ans=0,pi[25];
    11 int f[25][25]={0},a[25][25],b[25][25];
    12 
    13 void Work(int x){
    14      if(x>3) Work(x/2);
    15      if(x==1) return ;
    16      
    17      memset(a,0,sizeof(a));
    18      for(int i=0;i<m;++i)
    19      for(int j=0;j<m;++j)
    20      for(int k=0;k<m;++k)
    21      a[i][j]=(a[i][j]+f[i][k]*f[k][j])%mod;
    22      
    23      memcpy(f,a,sizeof(a));
    24      
    25      if(x%2)
    26      {
    27        memset(a,0,sizeof(a));
    28        for(int i=0;i<m;++i)
    29        for(int j=0;j<m;++j)
    30        for(int k=0;k<m;++k)
    31        a[i][j]=(a[i][j]+f[i][k]*b[k][j])%mod;
    32        
    33        memcpy(f,a,sizeof(f));
    34             }
    35      }
    36 
    37 void Kmp(){
    38      for(int i=2;i<s.size();++i)
    39      {
    40        int x=pi[i-1];      
    41        while(s[i]!=s[x+1]&&x!=0) x=pi[x];                       
    42        if(s[i]==s[x+1]) pi[i]=x+1;                     
    43              }
    44      }
    45 
    46 void Prepare(){
    47      for(int i=0;i<s.size()-1;++i)
    48      for(int j=0;j<=9;++j)
    49      {
    50        int x=i;                     //小心观看 
    51        while(x!=0&&j!=s[x+1]-'0') x=pi[x];
    52        if(j==s[x+1]-'0') f[i][x+1]++;
    53        else f[i][0]++; 
    54              }
    55      memcpy(b,f,sizeof(f));
    56      }
    57 
    58 int main()
    59 {
    60     cin>>n>>m>>mod>>s;
    61     s=" "+s;
    62     Kmp();
    63     
    64     Prepare();
    65     
    66     Work(n);
    67     
    68     for(int i=0;i<m;++i) ans+=f[0][i];
    69     
    70     cout<<ans%mod<<endl;
    71    // system("pause");
    72     return 0;
    73     
    74     }
     
  • 相关阅读:
    二分查找法的实现和应用汇总
    hdu 3062 Party 2SAT入门
    network monitor 抓包软件 微软的 架构师提供的
    富文本编辑器
    分享图标
    js日期时间控件
    jquery form
    javascript学习站
    sql生成model类
    PHP学习
  • 原文地址:https://www.cnblogs.com/noip/p/2962560.html
Copyright © 2011-2022 走看看