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

    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

    HINT

     

    Source

     

    利用“不吉利数字”构建ac自动机(我好像小题大做了,一个串好像没有必要),构建初始矩阵,接着矩阵乘法即可。

    初始矩阵a[i][j]表示走一步从i节点走到j节点的方案数。

    code:

      1 #include<vector>
      2 #include<queue>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<cstdlib>
      6 using namespace std;
      7 
      8 #define maxm 25
      9 char buf[maxm];
     10 int n,m,rhl,ans;
     11 
     12 struct node
     13 {
     14     int a[maxm*maxm][maxm*maxm],n,m;
     15     node() {memset(a,0,sizeof(a));n = m = 0;}
     16 
     17     friend node operator *(node x,node y)
     18     {
     19         node z; z.n = x.n; z.m = y.m;
     20         int i,j,k;
     21         for (i = 1;i <= z.n;++i)
     22             for (j = 1;j <= z.m;++j)
     23                 for (k = 1;k <= x.m;++k)
     24                     (z.a[i][j] += (long long)x.a[i][k]*(long long)y.a[k][j]%rhl)%=rhl;
     25         return z;
     26     }
     27 
     28     inline node quick(node x,int k)
     29     {
     30         node ret; ret.n = x.n; ret.m = x.m;
     31         for (int i = 1;i <= ret.n;++i) ret.a[i][i] = 1;        
     32         for (;k;k>>=1,x = x*x)
     33             if (k & 1)
     34                 ret = ret*x;
     35         return ret;
     36     }
     37 
     38     inline void calc() { for (int i = 0;i <= m;++i) (ans += a[1][i])%=rhl; }
     39 }s;
     40 
     41 struct trie
     42 {
     43     int next[maxm][10],fail[maxm],L,root;
     44     bool end[maxm];
     45     inline int newnode()
     46     {
     47         memset(next[L],-1,sizeof(next[L]));
     48         return ++L-1;
     49     }
     50 
     51     inline void init() {L = 0; root = newnode();}
     52     
     53     inline void insert()
     54     {
     55         int len = strlen(buf),now = root,i;
     56         for (i = 0;i < len;++i)
     57         {
     58             if (next[now][buf[i]-'0'] == -1) next[now][buf[i]-'0'] = newnode();
     59             now = next[now][buf[i]-'0'];
     60         }
     61         end[now] = true;
     62     }
     63 
     64     inline void build()
     65     {
     66         int now = root,i; queue <int> team;
     67         fail[root] = root;
     68         for (i = 0;i < 10;++i)
     69             if (next[now][i] == -1) next[now][i] = root;
     70             else fail[next[now][i]] = root,team.push(next[now][i]);
     71         while (!team.empty())
     72         {
     73             now = team.front(); team.pop();
     74             for (i = 0;i < 10;++i)
     75                 if (next[now][i] == -1) next[now][i] = next[fail[now]][i];
     76                 else fail[next[now][i]] = next[fail[now]][i],team.push(next[now][i]);
     77         }
     78     }
     79 
     80     inline void ready()
     81     {
     82         vector <int> son[maxm]; queue <int> team; int i,now,v,nn;
     83         for (i = 0;i < L;++i) if (fail[i] != i) son[fail[i]].push_back(i);
     84         team.push(root);
     85         while (!team.empty())
     86         {
     87             now = team.front(); team.pop();
     88             nn = son[now].size();
     89             for (i = 0;i < nn;++i)
     90             {
     91                 v = son[now][i];
     92                 if (end[now]) end[v] = true;
     93                 team.push(v);
     94             }    
     95         }
     96     }
     97 
     98     inline void make()
     99     {
    100         int i,j; s.n = s.m = L;
    101         for (i = 0;i < L;++i)
    102         {
    103             if (end[i]) continue;
    104             for (j = 0;j < 10;++j)
    105                 if (!end[next[i][j]]) s.a[i+1][next[i][j]+1]++;
    106         }
    107     }
    108 }ac;
    109 
    110 int main()
    111 {
    112     freopen("1009.in","r",stdin);
    113     freopen("1009.out","w",stdout);
    114     scanf("%d %d %d
    ",&n,&m,&rhl);
    115     ac.init();
    116     scanf("%s",buf); ac.insert();
    117     ac.build(); ac.ready(); ac.make();
    118     s = s.quick(s,n); s.calc();
    119     printf("%d",ans);
    120     fclose(stdin); fclose(stdout);
    121     return 0;
    122 }
    View Code
  • 相关阅读:
    jq 的简单循环
    简单的下拉菜单
    jQ事件
    图片移动
    选中效果
    js 时间
    简单的密码验证
    DOM 的简介 和一些方法
    Java编程思想笔记
    Java并发笔记(二)
  • 原文地址:https://www.cnblogs.com/mmlz/p/4226111.html
Copyright © 2011-2022 走看看