1646:GT 考试
时间限制: 1000 ms 内存限制: 524288 KB【题目描述】
阿申准备报名参加 GT 考试,准考证号为 ,他不希望准考证号上出现不吉利的数字。
他的不吉利数字 0。
【输入】
第一行输入 m 位的数。
【输出】
阿申想知道不出现不吉利数字的号码有多少种,输出模 取余的结果。
【输入样例】
4 3 100
111
【输出样例】
81
【提示】
数据范围与提示:
对于全部数据,。
sol:此题应该是先想到暴力的做法再用矩阵乘法优化的
所以暴力的思想很重要
dp[i][j]表示到第i位,匹配了j个的方案数
先预处理出f[i][j]表示已经匹配了i个,加一个数字变成匹配了j个方案数,i,j<=m-1,用kmp搞搞
转移就不难了,dp[i][j]+=dp[i-1][k]*f[k][j],是不是很像矩阵乘法2333
#include <bits/stdc++.h> using namespace std; typedef int ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar('\n') const int N=100005,M=25; int n,m,Mod; int Num[25],f[25][25]; int dp[N][M]; inline void Ad(int &x,int y) { x+=y; x-=(x>=Mod)?Mod:0; return; } int Next[25]; inline void Pre_f() { int i,j=0; Next[1]=0; for(i=2;i<=m;i++) { while((Num[j+1]!=Num[i])&&j) j=Next[j]; if(Num[j+1]==i) j++; Next[i]=j; } for(i=0;i<m;i++) { for(j=0;j<=9;j++) { int Now=i; while((Num[Now+1]!=j)&&Now) Now=Next[Now]; if(Num[Now+1]==j) Now++; f[i][Now]++; } } /* for(i=0;i<m;i++,puts("")) { for(j=0;j<m;j++) W(f[i][j]); } puts(""); */ return; } int main() { int i,j,k,ans=0; R(n); R(m); R(Mod); for(i=1;i<=m;i++) { char ch=' '; while(!isdigit(ch)) ch=getchar(); Num[i]=ch-'0'; } Pre_f(); dp[0][0]=1; for(i=1;i<=n;i++) { for(j=0;j<=m-1;j++) { for(k=0;k<=m-1;k++) { Ad(dp[i][j],dp[i-1][k]*f[k][j]%Mod); } } } for(i=0;i<m;i++) Ad(ans,dp[n][i]); Wl(ans); return 0; } /* input 4 3 100 111 output 81 */