1. 程式人生 > >【bzoj1009】[HNOI2008]GT考試

【bzoj1009】[HNOI2008]GT考試

吉利 problem 快速 www. string 直接 bsp pro click

  題目傳送門:https://www.lydsy.com/JudgeOnline/problem.php?id=1009

  這道題一看數據範圍:$ n<=10^9 $,顯然不是數學題就是矩乘快速冪優化dp。

  我們設$ f[i][j] $表示前$ i $位匹配不吉利數字$ j $位時的方案數,因為每一位的轉移方式都是相同的,於是用kmp預處理出轉移矩陣,直接矩乘快速冪就能過了。

技術分享圖片
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include
<ctime> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<map> #define ll long long #define ull unsigned long long #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define lowbit(x) (x& -x) #define inf 0x3f3f3f3f #define
eps 1e-18 #define maxn 100010 inline ll read(){ll tmp=0; char c=getchar(),f=1; for(;c<0||9<c;c=getchar())if(c==-)f=-1; for(;0<=c&&c<=9;c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-0; return tmp*f;} inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} inline void swap(int &a,int
&b){int tmp=a; a=b; b=tmp;} using namespace std; struct matrix{ int size; int num[30][30]; }ans; int nxt[30]; char s[30]; int n,m,mod; matrix mul(matrix a,matrix b) { matrix c; memset(&c,0,sizeof(c)); c.size=a.size; for(int i=1;i<=a.size;i++) for(int j=1;j<=a.size;j++) for(int k=1;k<=a.size;k++) c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j])%mod; return c; } matrix power(matrix a,ll b) { matrix ans; memset(&ans,0,sizeof(ans)); ans.size=a.size; for(int i=1;i<=ans.size;i++)ans.num[i][i]=1; for(;b;b>>=1){ if(b&1)ans=mul(ans,a); a=mul(a,a); } return ans; } int main() { n=read(); m=read(); mod=read(); scanf("%s",s); nxt[1]=0; int tmp=0; for(int i=1;i<=m;i++){ while(tmp&&s[i]!=s[tmp])tmp=nxt[tmp]; if(s[i]==s[tmp])++tmp; nxt[i+1]=tmp; } for(int i=0;i<m;i++) for(int j=0;j<=9;j++){ int tmp=i; while(tmp&&j!=s[tmp])tmp=nxt[tmp]; if(j==s[tmp])++tmp; if(tmp<m)++ans.num[i+1][tmp+1]; } ans.size=m; ans=power(ans,n); int tot=0; for(int i=1;i<=m;i++) tot+=ans.num[1][i]; printf("%d\n",tot%mod); }
bzoj1009

【bzoj1009】[HNOI2008]GT考試