zoukankan      html  css  js  c++  java
  • bzoj-1009-dp+kmp处理转移矩阵幂

    1009: [HNOI2008]GT考试

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 4723  Solved: 2940
    [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位的数。 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时的方案个数,它可以推出的状态就是->f[i+1][k],下一步可以选择的数字[0,9],根据失配指针寻找应该转移到的状态k就好了,就是AC自动机,只不过是单链的为了方便用kmp处理。显然所有的f[i+1][]状态都来自于
    f[i][],于是想到利用转移矩阵A,实现 (f[i][0],f[i][1],,,f[i][m])*A=(f[i+1][0],f[i+1][1],,,,f[i+1][m]),矩阵A[i][j]表示f[i+1][j]+=A[i][j]*f[i][j].
     1 #include<iostream>
     2 #include<cstring>
     3 #include<queue>
     4 #include<cstdio>
     5 #include<stack>
     6 #include<set>
     7 #include<map>
     8 #include<cmath>
     9 #include<ctime>
    10 #include<time.h> 
    11 #include<algorithm>
    12 #include<bits/stdc++.h>
    13 using namespace std;
    14 #define mp make_pair
    15 #define pb push_back
    16 #define debug puts("debug")
    17 #define LL  long long 
    18 #define pii pair<int,int>
    19 #define eps 1e-10
    20 #define inf 0x3f3f3f3f
    21   
    22 LL N,M,K;
    23 int f[22];
    24 char s[22];
    25 struct matrix{
    26     LL len;
    27     LL a[22][22];
    28     matrix(){
    29         memset(a,0,sizeof(a));
    30     }
    31     matrix& operator*(matrix& tmp){
    32         matrix ans;
    33         ans.len=len;
    34         for(int i=0;i<=len;++i){
    35             for(int j=0;j<=len;++j){
    36                 for(int k=0;k<=len;++k){
    37                     ans.a[i][k]+=a[i][j]*tmp.a[j][k];
    38                     ans.a[i][k]%=K;
    39                 }
    40             }
    41         }
    42         return ans;
    43     }
    44       
    45 }A,I;
    46 matrix qpow(matrix X,int n){
    47     matrix ans=I;
    48     while(n){
    49         if(n&1) ans=ans*X;
    50         X=X*X;
    51         n>>=1;
    52     }
    53     return ans;
    54 }
    55 void init(){
    56     int i,j,k,len;
    57     I.len=A.len=M;
    58     for(i=0;i<=M;++i)I.a[i][i]=1;
    59     len=strlen(s+1);
    60     f[0]=0;
    61     f[1]=0;
    62     for(i=2;i<=len;++i){
    63         j=f[i-1];
    64         while(j&&s[j]!=s[i-1]) j=f[j];
    65         f[i]=j+1;
    66     }
    67  
    68     for(i=0;i<len;++i){
    69         for(j=0;j<10;++j){
    70             if(s[i+1]-'0'==j){
    71                 A.a[i][i+1]++;
    72             }
    73             else{
    74                 k=f[i+1];
    75                 while(k&&s[k]-'0'!=j) k=f[k];
    76                 A.a[i][k]++;
    77             }
    78         }
    79     }
    80     A.a[len-1][len]=0;
    81     
    82 }
    83 int main(){
    84     int i,j,k;
    85     scanf("%lld%lld%lld",&N,&M,&K);
    86     scanf("%s",s+1);
    87     init();
    88     matrix ans=qpow(A,N);
    89     LL res=0;
    90     for(i=0;i<=ans.len;++i){
    91         res+=ans.a[0][i];
    92         res%=K;
    93     }
    94     cout<<res<<endl;
    95     return 0;
    96 }
  • 相关阅读:
    国内顺利使用Google的另类技巧
    Java进程间通信
    Java 多线程(七) 线程间的通信——wait及notify方法
    转:关于copy_to_user()和copy_from_user()的一些用法
    转: pthread_detach()函数
    转:pthread_create()
    转: ubuntu配置NFS,挂载开发板
    转:全志A20 GPIO 总结文档
    转:Linux 内核中的 cdev_alloc和cdev_add
    转:1.1 cdev_init cdev_alloc 使用说明
  • 原文地址:https://www.cnblogs.com/zzqc/p/9034517.html
Copyright © 2011-2022 走看看