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

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 2486  Solved: 1524
    [Submit][Status][Discuss]

    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位的数。 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
     
    题解:
      首先想暴力的算法,假设构造出一个字符串来和A串进行匹配,f[i][j]代表前i个位置的数中后缀有j位是匹配的,当前要在第i+1个位置新加入一个数字k,看此时对f[i+1][x]的贡献,来更新f[i+1][x]。
    ①:如果k==A[j+1],则f[i+1][j+1]+=f[i][j]   
    ②:如果不相等,让 j 根据对于A串构造出的next[]进行跳转,直到跳转后的j使得A[j+1]==k,即f[i+1][tmp+1]=f[i+1][tmp+1]+f[i][j]
    :如果以上两种情况都不满足的话,就看看k是不是和A[1]相等,如果相等:f[i+1][1]=f[i+1][1]+f[i][j]
    ④:实在没法匹配,就只能f[i+1][0]=f[i+1][0]+f[i][j]
    最后:for(LL j=0;j<=M-1;j++) ans+=(f[N][j])%mod,ans%=mod; 得出是就是答案。
      40分暴力:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 LL N,M,K;
     5 LL f[2000][30],next[30],lenA,A[30],ans,mod;
     6 char s[30];
     7 int main(){
     8     scanf("%lld%lld%lld%s",&N,&M,&K,s+1); lenA=strlen(s+1); mod=K;
     9     for(LL i=1;i<=lenA;i++) A[i]=s[i]-'0';
    10     for(LL j=0,i=2;i<=lenA;i++){
    11         while(A[j+1]!=A[i]&&j) j=next[j];
    12         if(A[j+1]==A[i]) j++;
    13         next[i]=j;
    14     }
    15     f[1][0]=9; f[1][1]=1;
    16     for(LL i=1;i<=N-1;i++){//前 i个字符 
    17         for(LL j=0;j<=min(M-1,i);j++){//末尾有j位匹配 
    18             for(LL k=0;k<=9;k++){//再加入数字 k 
    19                 LL tmp=j; bool vis=false;
    20                 if(A[tmp+1]==k){
    21                 f[i+1][j+1]=(f[i+1][j+1]+f[i][j]%mod)%mod;
    22                     vis=true;
    23                     continue;
    24                 }
    25                 else{
    26                     while(next[tmp]!=0){
    27                         tmp=next[tmp];
    28                         if(A[tmp+1]==k){
    29                             f[i+1][tmp+1]=(f[i+1][tmp+1]+f[i][j]%mod)%mod;
    30                             vis=true;
    31                             break;
    32                         }
    33                     }
    34                 }
    35                 if(vis==false){
    36                     if(A[1]==k) f[i+1][1]=(f[i+1][1]+f[i][j]%mod)%mod;
    37                     else f[i+1][0]=(f[i+1][0]+f[i][j]%mod)%mod;
    38                 }
    39             }
    40         }
    41     }
    42     for(LL j=0;j<=M-1;j++) 
    43         ans+=(f[N][j])%mod,ans%=mod;
    44     printf("%lld",ans);
    45     return 0;
    46 }
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,m,mod,ans;
     4 char str[25];
     5 int next[25],s[25],a[25][25],c[25][25],f[25],d[25];
     6 int idx(char ch){
     7     return ch-'0';
     8 }
     9 void KMP(){
    10     for(int i=0;i<m;i++) s[i+1]=idx(str[i]);
    11     for(int j=0,i=2;i<=m;i++){
    12         while(j&&s[j+1]!=s[i]) j=next[j];
    13         if(s[j+1]==s[i])++j;
    14         next[i]=j;
    15     }
    16 }
    17 void Makematrix(){//a[i][k]表示由匹配 i个到匹配 k个的方案数 
    18     for(int i=0;i<=m-1;i++){
    19         for(int j=0;j<=9;j++){
    20             int k=i;
    21             while(j!=s[k+1]&&k) k=next[k];
    22             if(s[k+1]==j) k++;
    23             a[i][k]++;
    24         }
    25     }
    26 }
    27 void muti1(){
    28     memset(d,0,sizeof(d));
    29     for(int i=0;i<m;i++)
    30         for(int j=0;j<m;j++)
    31             d[i]=(d[i]+f[j]*a[j][i])%mod;
    32     for(int i=0;i<m;i++) f[i]=d[i];
    33 }
    34 void muti2(){
    35     memset(c,0,sizeof(c));
    36     for(int i=0;i<m;i++)
    37         for(int j=0;j<m;j++)
    38             for(int k=0;k<m;k++)
    39                 c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
    40     for(int i=0;i<m;i++)
    41         for(int j=0;j<m;j++)a[i][j]=c[i][j];
    42 }
    43 int main(){
    44 //    freopen("bzoj_1009.in","r",stdin);
    45 //    freopen("bzoj_1009.out","w",stdout);
    46     scanf("%d%d%d",&n,&m,&mod);
    47     cin>>str;
    48     KMP(); Makematrix(); 
    49     f[0]=1;
    50     while(n){
    51         if(n&1) muti1();
    52         muti2(); n>>=1;
    53     }
    54     for(int i=0;i<m;i++)
    55         ans+=f[i];
    56     printf("%d
    ",ans%mod);
    57 }
  • 相关阅读:
    jq 的简单循环
    简单的下拉菜单
    jQ事件
    图片移动
    选中效果
    js 时间
    简单的密码验证
    DOM 的简介 和一些方法
    Java编程思想笔记
    Java并发笔记(二)
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5168257.html
Copyright © 2011-2022 走看看