描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1009
字符串全部由0~9組成,給出一個串s,求一個長度為n的串,不包含s的種類有多少.
?
分析
第一眼以為是組合.然后更滑稽的是用錯誤的方法手算樣例居然算出來是對的...我數學是有多差...
題解也是看了好半天,有點難理解.
感覺PoPoQQQ神犇講得還是比較清楚的.傳送門:http://blog.csdn.net/popoqqq/article/details/40188173
我們用dp[i][j]表示 : 長度為i的串, 其長度為j的后綴 與 s長度為j的前綴 完全匹配的種類數.
這樣的話最后的答案就是ans=sigma{dp[n][i]}(0<=i<m).
這里還有一個二維的a數組,就這個比較難解釋...
dp[i][y]可以由dp[i-1][x]轉移而來,那么匹配的s的前綴由長度x變成了長度y,a[x][y]表示的就是在結尾添加一個字符后,匹配長度從x變成y,這樣的字符有多少種.
那么 dp[i][y]=sigma{dp[i-1][x]*a[x][y]}.
這個可以用矩陣乘法算.
那么a數組怎么求呢?用kmp.
a[x][y]表示的是前綴匹配長度由x變成了y的種類數,那么從每一位i開始匹配,如果匹配到了j,那么a[i][j+1]++(數組從0開始,第i位之前匹配了i個,匹配到第j位,應該是j+1個).
?
p.s.我好菜呀...
?


1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=100+5; 5 int n,m,p,ans; 6 char str[maxn]; 7 int f[maxn]; 8 9 struct matrix{ 10 int x[25][25]; 11 matrix(){ memset(x,0,sizeof x); } 12 int * operator [] (int id){ return x[id]; } 13 }dp,a; 14 void operator *= (matrix &x,matrix &y){ 15 matrix z; 16 for(int i=0;i<m;i++)for(int j=0;j<m;j++)for(int k=0;k<m;k++) 17 z[i][j]+=x[i][k]*y[k][j], z[i][j]%=p; 18 x=z; 19 } 20 void kmp(){ 21 for(int i=1;i<m;i++){ 22 int j=f[i]; 23 while(j&&str[i]!=str[j]) j=f[j]; 24 f[i+1]=str[i]==str[j]?j+1:0; 25 } 26 for(int i=0;i<m;i++)for(char k='0';k<='9';k++){ 27 int j=i; 28 while(j&&k!=str[j]) j=f[j]; 29 if(k==str[j]) a[i][j+1]++; 30 else a[i][0]++; 31 } 32 } 33 void quick_power(int y){ 34 for(;y;a*=a,y>>=1) if(y&1) dp*=a; 35 } 36 int main(){ 37 scanf("%d%d%d",&n,&m,&p); 38 scanf("%s",str); 39 kmp(); 40 dp[0][0]=1; 41 quick_power(n); 42 for(int i=0;i<m;i++) ans+=dp[0][i], ans%=p; 43 printf("%d\n",ans); 44 return 0; 45 }
?
1009: [HNOI2008]GT考試
Time Limit: 1 Sec??Memory Limit: 162 MBSubmit: 2815??Solved: 1738
[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
111