【刷題】BZOJ 3262 [HNOI2008]GT考試
阿新 • • 發佈:2018-03-29
gpo operator max markdown 一位 枚舉 return 思想 設計
按照數位dp的思想依次考慮每一位上的數字,考慮設計dp,\(f[i][j]\) 代表考慮完第 \(i\) 位之後,後 \(j\) 位與不吉利數字的前 \(j\) 位相同的方案數
那麽最後答案為 \(ans=\sum_{i=0}^{m-1}f[n][i]\)
現在新加進來一個數,對之前的相同的 \(j\) 位造成的影響會有三種情況:
再進一步,\(f[i][j]=\sum_{k=0}^{m-1}f[i-1][k]*a[k][j]\),其中 \(a[k][j]\) 代表從匹配好 \(k\) 位變成匹配 \(j\) 位的方案數
對於 \(a\) 數組,先KMP求出fail/next數組,然後直接枚舉每個位置上的每個數,相當於暴力求得
對於 \(f\) 數組,看上面的式子難道不眼熟嗎,這東西顯然可以矩陣快速冪優化
然後答案就出來了
註意一下每個人的KMP寫法都不一樣,求的fail/next數組也會有所不同,但只要能達到效果就可以了,不同的寫法最後算 \(a\) 的時候,細節略有不同
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
Solution
這題還是很無奈的
那麽最後答案為 \(ans=\sum_{i=0}^{m-1}f[n][i]\)
現在新加進來一個數,對之前的相同的 \(j\) 位造成的影響會有三種情況:
- 延長原有的 \(j\) 位,變成 \(j+1\) 位
- 直接把原有的 \(j\) 位打回0位
- 把原來的 \(j\) 位變短到一個位置,而這個位置,你會發現正好是KMP中求的fail/next數組
那麽,\(f[i][j]=f[i-1][j-1]+\sum_{k=1}^mf[i-1][k]*[next[k]=j-1]\)
再進一步,\(f[i][j]=\sum_{k=0}^{m-1}f[i-1][k]*a[k][j]\),其中 \(a[k][j]\) 代表從匹配好 \(k\) 位變成匹配 \(j\) 位的方案數
對於 \(a\) 數組,先KMP求出fail/next數組,然後直接枚舉每個位置上的每個數,相當於暴力求得
對於 \(f\) 數組,看上面的式子難道不眼熟嗎,這東西顯然可以矩陣快速冪優化
然後答案就出來了
註意一下每個人的KMP寫法都不一樣,求的fail/next數組也會有所不同,但只要能達到效果就可以了,不同的寫法最後算 \(a\) 的時候,細節略有不同
#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
const int MAXM=400+5;
int n,m,Mod,ans,nexts[MAXM];
char s[MAXM];
struct Matrix{
int a[MAXM][MAXM];
inline void init()
{
memset(a,0,sizeof(a));
}
inline Matrix operator * (const Matrix &A) const {
Matrix B;
for(register int i=0;i<m;++i)
for(register int j=0;j<m;++j)
{
B.a[i][j]=0;
for(register int k=0;k<m;++k)(B.a[i][j]+=(a[i][k]*A.a[k][j]))%=Mod;
}
return B;
};
};
Matrix A,B;
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void KMP()
{
nexts[0]=-1;
for(register int i=1;i<m;++i)
{
int j=nexts[i-1];
while(s[i]!=s[j+1]&&j>=0)j=nexts[j];
if(s[i]==s[j+1])nexts[i]=j+1;
else nexts[i]=-1;
}
}
inline void init()
{
KMP();
for(register int i=0;i<m;++i)
for(register int j='0';j<='9';++j)
{
int k=i;
while(k&&s[k]!=j)k=nexts[k-1]+1;
if(s[k]==j)k++;
if(k!=m)B.a[i][k]++;
}
}
inline Matrix Fast_Matrix(int k)
{
Matrix res;
res.init();
res=B;
--k;
while(k)
{
if(k&1)res=res*B;
B=B*B;
k>>=1;
}
return res;
}
int main()
{
read(n);read(m);read(Mod);
A.init();B.init();
scanf("%s",s);
init();
A.a[0][0]=1;
B=Fast_Matrix(n);
A=A*B;
for(register int i=0;i<m;++i)(ans+=A.a[0][i])%=Mod;
write(ans,'\n');
return 0;
}
【刷題】BZOJ 3262 [HNOI2008]GT考試