您的位置:首页 > 其它

bzoj1009 [HNOI2008]GT考试

2018-02-23 12:03 465 查看

1009: [HNOI2008]GT考试

Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 4517 Solved: 2799
[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
分析:以前做过一道类似的题:传送门,但是本题的n特别大,不能存到状态里面,怎么办?

   如果当前匹配到不吉利数字的号码的第j位,枚举第j+1位的数字,能够转移到的地方是固定的. 构造一个转移矩阵,令a[i][j]表示不吉利数字的第i位跳到第j位有多少种方案. 这个很容易利用kmp算法求出来.那么f[i][j] = f[i-1][0] * a[0][j] + f[i - 1][1] * a[1][j] +......
这是一个矩阵相乘的表达式,可以用矩阵快速幂来优化.
   通过矩阵快速幂,可以不用记录n,最后的答案就是矩阵第一行的和.因为第m列是不符合要求的,所以实际上只需要记录矩阵的0~m-1列即可.
   这道题的转移方式和那道题有很大的区别. 因为要用到矩阵快速幂不记录n,必须知道f[i][j]从哪些状态转移而来,转移过来的方案数是多少,那么就必须要求出a数组. 相反的,如果直接递推转移,那么很容易就能知道f[i][j]能够转移到哪些状态,直接从f[i][j] 转移到f[i + 1][k]即可.由此可以看出“转移到”和“转移来”有很大的区别,记录的东西也会有所不同.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n,m,mod,nextt[30],ans;
char s[30];

struct node
{
int x[30][30];
void clear()
{
memset(x,0,sizeof(x));
}
}a,b,c;

void operator *= (node &p,node &q)
{
c.clear();
for (int i = 0; i < m; i++)
for (int j = 0; j < m; j++)
for (int k = 0; k < m; k++)
c.x[i][j] = (c.x[i][j] + p.x[i][k] * q.x[k][j] % mod) % mod;
p = c;
}

void kmp()
{
int j = 0;
for (int i = 2; i <= m; i++)
{
while (j && s[j + 1] != s[i])
j = nextt[j];
if (s[j + 1] == s[i])
j++;
nextt[i] = j;
}
int k;
b.clear();
for (int i = 0; i < m; i++)
{
for (char j = '0'; j <= '9'; j++)
{
k = i;
while (k && s[k + 1] != j)
k = nextt[k];
if (s[k + 1] == j)
k++;
b.x[i][k]++;
}
}
}

void qpow(int p)
{
a.clear();
for (int i = 0; i < m; i++)
a.x[i][i] = 1;
while (p)
{
if (p & 1)
a *= b;
b *= b;
p >>= 1;
}
}

int main()
{
scanf("%d%d%d",&n,&m,&mod);
scanf("%s",s + 1);
kmp();
qpow(n);
for (int i = 0; i < m; i++)
ans = (ans + a.x[0][i]) % mod;
printf("%d\n",ans);

return 0;
}


   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: