bzoj4037 [HAOI2015]数字串拆分
Description
你有一个长度为n的数字串。定义f(S)为将S拆分成若干个1~m的数的和的方案数,比如m=2时,f(4)=5,分别为4=1+1+1+1你可以将这个数字串分割成若干个数字(允许前导0),将他们加起来,求f,并求和。比如g(123)=f(1+2+3)+f(1+23)+f(12+3)+f(123)。已知字符串和m后求答案对998244353(7×17×223+1,一个质数)取模后的值。
Input
第一行输入一个字符串,第二行输入m
Output
仅输出一个数表示答案
Sample Input
123
3
3
Sample Output
394608467
HINT
对于100%的数据,字符串长度不超过500,m<=5
正解:$dp$+矩阵乘法。
矩阵可以用来$dp$转移。。
设$g[i]$表示$i$的拆分数,那么$g[i]=\sum_{j=0}^{m}g[i-j]$,这显然可以用矩阵表示,设转移矩阵为$A$。
然后我们设$f[i]$表示字符串到$i$的方案数。我们可以发现$A^{a1+a2+...+ak}=A^{a1}*A^{a2}*...*A^{ak}$。
那么我们把$f$也变成矩阵,则$f[i]=\sum_{j=0}^{i-1}f[j]*A^{s[j+1]...s[i]}$,因为矩阵可以加法,满足分配律,所以这里是对的。
预处理出$(A^{10^{r}})^{k}$,然后直接$dp$即可。复杂度$O(m^{3}*n^{2})$。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define rhl (998244353) 6 7 using namespace std; 8 9 struct data{ int m[6][6]; }A[505][10],f[505],now; 10 11 char s[505]; 12 int n,m; 13 14 il int gi(){ 15 RG int x=0,q=1; RG char ch=getchar(); 16 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 17 if (ch=='-') q=-1,ch=getchar(); 18 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 19 return q*x; 20 } 21 22 il void add(data &a,data b){ 23 for (RG int i=1;i<=m;++i) 24 for (RG int j=1;j<=m;++j){ 25 a.m[i][j]+=b.m[i][j]; 26 if (a.m[i][j]>=rhl) a.m[i][j]-=rhl; 27 } 28 return; 29 } 30 31 il data mul(data a,data b){ 32 data c; memset(c.m,0,sizeof(c.m)); 33 for (RG int i=1;i<=m;++i) 34 for (RG int j=1;j<=m;++j) 35 for (RG int k=1;k<=m;++k) 36 c.m[i][k]=(1LL*a.m[i][j]*b.m[j][k]+c.m[i][k])%rhl; 37 return c; 38 } 39 40 int main(){ 41 #ifndef ONLINE_JUDGE 42 freopen("split.in","r",stdin); 43 freopen("split.out","w",stdout); 44 #endif 45 scanf("%s",s+1),n=strlen(s+1),m=gi(); 46 for (RG int i=1;i<=m;++i) 47 for (RG int j=1;j<=m;++j) A[0][0].m[i][j]=i==j; 48 for (RG int i=1;i<m;++i) A[0][1].m[i+1][i]=1; 49 for (RG int i=1;i<=m;++i) A[0][1].m[i][m]=1; 50 for (RG int i=2;i<10;++i) A[0][i]=mul(A[0][i-1],A[0][1]); 51 for (RG int i=1;i<=n;++i){ 52 A[i][0]=A[0][0],A[i][1]=mul(A[i-1][9],A[i-1][1]); 53 for (RG int j=2;j<10;++j) A[i][j]=mul(A[i][j-1],A[i][1]); 54 } 55 f[0]=A[0][0]; 56 for (RG int i=1;i<=n;++i){ 57 now=A[0][s[i]-'0']; 58 for (RG int j=i-1;~j;--j){ 59 add(f[i],mul(f[j],now)); 60 if (j) now=mul(A[i-j][s[j]-'0'],now); 61 } 62 } 63 cout<<f[n].m[m][m]; return 0; 64 }