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

    题目大意:

    准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数

    他的不吉利数A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am

    A1和X1可以为0

    思路:

    dp i j 为第i个号码匹配到第j个不吉利数字的方案数

    可以得到:dp[i][j]=∑dp[i1][k]∗t[k][j](0<=k<=m1)

    其中t数组为第i位加的字符的方案数使从匹配k位到匹配j位的方案数

    可以使用kmp算法来求出t数组

    然后这个式子可以矩阵乘法加速

    同样在图上填一填数 

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstdlib>
     6 #include<cstring>
     7 #include<queue>
     8 #include<map>
     9 #include<vector>
    10 #define ll long long
    11 #define inf 2147483611
    12 #define MAXN 1010
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n,m,MOD,nxt[25];
    22 char str[25];
    23 struct mat{int num[25][25];}ans,t;
    24 mat mul(mat a,mat b)
    25 {
    26     mat res;
    27     memset(res.num,0,sizeof(res.num));
    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                 (res.num[i][j]+=a.num[i][k]*b.num[k][j])%=MOD;
    32     return res;
    33 }
    34 int q_pow(int n)
    35 {
    36     int res=0;
    37     while(n)
    38     {
    39         if(n&1) ans=mul(ans,t);
    40         t=mul(t,t);
    41         n>>=1;
    42     }
    43     for(int i=0;i<m;i++) (res+=ans.num[0][i])%=MOD;
    44     return res;
    45 }
    46 int main()
    47 {
    48     n=read(),m=read(),MOD=read();
    49     scanf("%s",str+1);int j=0,tmp;
    50     for(int i=2;i<=m;i++)
    51     {
    52         while(j&&str[j+1]!=str[i]) j=nxt[j];
    53         if(str[j+1]==str[i]) j++;
    54         nxt[i]=j;
    55         //cout<<i<<" "<<nxt[i]<<endl;
    56     }
    57     memset(t.num,0,sizeof(t.num));
    58     memset(ans.num,0,sizeof(ans.num));
    59     for(int i=0;i<m;i++)
    60         for(int j=0;j<=9;j++)
    61         {
    62             tmp=i;
    63             while(tmp&&str[tmp+1]!=(char)(j+'0')) tmp=nxt[tmp];
    64             if(str[tmp+1]==(char)(j+'0')) tmp++;
    65             if(tmp!=m) t.num[i][tmp]++;
    66             //cout<<i<<" "<<tmp<<endl;
    67         }
    68     for(int i=0;i<m;i++) ans.num[i][i]=1;
    69     printf("%d",q_pow(n));
    70 }
    View Code
  • 相关阅读:
    Redisson 实现分布式锁原理分析
    redis如何避免释放锁时把别人的锁释放掉
    记一次org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only异常
    1.编译chromium
    Win10更新后wireshark无法获取网络接口
    ASIO库使用注意事项
    使用gdb添加断点的几种方式
    select、poll、epoll的比较
    CMakeLists.txt编写常用命令
    Ubuntu下使用linuxdeployqt打包Qt程序
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/7943775.html
Copyright © 2011-2022 走看看