• Bzoj1009 [HNOI2008]GT考试


    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 2872  Solved: 1769

    Description

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

    Input

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

    Output

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

    Sample Input

    4 3 100
    111

    Sample Output

    81

    HINT

    Source

    动归。

    用f[i][j]表示填到第i位,不吉利串匹配到第j位的方案数,动态规划。

    kmp预处理出不吉利串的next数组,这样就可以利用next,在填每一位数时进行状态转移(如果填的下一个数能匹配,则匹配长度++,否则跳到next)

    之后用矩阵乘法计算总方案数

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 int n,m,k;
     8 int next[500];
     9 char ch[30];
    10 int a[30][30],b[30][30];
    11 void getnext(char s[]){
    12     next[0]=next[1]=0;
    13     int i,j;
    14     for(i=2,j=0;i<=m;i++){
    15         while(j && s[j+1]!=s[i])j=next[j];
    16         if(s[j+1]==s[i])j++;
    17         next[i]=j;
    18     }
    19     return;
    20 }
    21 void multi(int a[30][30],int b[30][30],int ans[30][30],int mod){
    22     int tmp[30][30];
    23     int i,j,k;
    24     for(i=0;i<m;i++)
    25       for(j=0;j<m;j++){
    26           tmp[i][j]=0;
    27           for(k=0;k<m;k++)
    28               tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod;
    29       }
    30     for(i=0;i<m;i++)
    31       for(j=0;j<m;j++)
    32           ans[i][j]=tmp[i][j];
    33 }
    34 int main(){
    35     scanf("%d%d%d",&n,&m,&k);
    36     scanf("%s",ch+1);
    37     getnext(ch);
    38     int i,j;
    39     //
    40     for(i=0;i<m;i++)
    41       for(j=0;j<=9;j++){
    42           int t=i;
    43           while(t && ch[t+1]-'0'!=j) t=next[t];
    44         if(ch[t+1]-'0'==j)t++;
    45         if(t!=m)b[t][i]=(b[t][i]+1)%k;//转移 
    46       }
    47     //
    48     for(i=0;i<m;i++)a[i][i]=1;
    49     while(n){
    50         if(n&1)multi(a,b,a,k);
    51         multi(b,b,b,k);
    52         n>>=1;
    53     }
    54     int sum=0;
    55     for(i=0;i<m;i++)sum=(sum+a[i][0])%k;//累计
    56     printf("%d
    ",sum);
    57     return 0;
    58 }
  • 相关阅读:
    WebView&HTML5-----使用WebView播放HTML5视频文件
    iOS中FMDB的使用
    Android Studio快速集成讯飞SDK实现文字朗读功能
    NSURLSession下载
    Android传感器应用——重力传感器实现滚动的弹球
    iOS开发中FMDB的使用
    Android WindowManager实现悬浮窗效果 (一)——与当前Activity绑定
    ABP理论学习之数据传输对象(DTO)
    ABP理论学习之应用服务
    ABP理论学习之数据过滤器
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5678158.html
Copyright © 2020-2023  润新知