[HAOI2015]数字串拆分

题目描述

你有一个长度为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,一个质数)取模后的值。

输入输出格式

输入格式:

第一行输入一个字符串,第二行输入m

输出格式:

仅输出一个数表示答案

输入输出样例

输入样例#1: 复制
123
3
输出样例#1: 复制
394608467

说明

对于100%的数据,字符串长度不超过500,m<=5

先求出$f[s]$

显然$f[i]=\sum_{j=i-m}^{i-1}f[j]$

如果i特别大就可以用一个m*m的转移矩阵

也就是$(f_{i-m+1},f_{i-m+2},...f_{i})$的转移矩阵

预处理出A[i][j]表示数S为j*10^i的转移矩阵

对于$g$的转移:

显然$g[i]=\sum_{j=0}^{i-1}g[j]*D[j+1][i]$

$D[j+1][i]$表示j+1~i位构成的数的转移矩阵,显然可以通过A推出

g也要用一个矩阵表示

g[0]初始矩阵使$g_0=1$,也就是$(0,0,..,0,1)$

最后输出矩阵中代表$g_n$的方案,位置是(1,m)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 int Mod=998244353;
 8 struct Matrix
 9 {
10     int a[6][6];
11 }f[501],A[501][10],now;
12 char s[502];
13 int n,m,ans;
14 Matrix operator *(const Matrix &a,const Matrix &b)
15 {
16     int i,j,l;
17     Matrix res;
18     memset(res.a,0,sizeof(res.a));
19     for (i=1; i<=m; i++)
20     {
21         for (j=1; j<=m; j++)
22         {
23             for (l=1; l<=m; l++)
24             {
25                 res.a[i][j]+=1ll*a.a[i][l]*b.a[l][j]%Mod;
26             if (res.a[i][j]>=Mod)
27             res.a[i][j]-=Mod;
28             }
29         }
30     }
31     return res;
32 }
33 Matrix operator +(const Matrix &a,const Matrix &b)
34 {
35     int i,j,l;
36     Matrix res;
37     memset(res.a,0,sizeof(res.a));
38     for (i=1; i<=m; i++)
39     {
40         for (j=1; j<=m; j++)
41         {
42         res.a[i][j]=(a.a[i][j]+b.a[i][j])%Mod;
43         }
44     }
45     return res;
46 }
47 int main()
48 {int i,j;
49   cin>>s+1;
50   n=strlen(s+1);
51   cin>>m;
52   for (i=1;i<=m;i++)
53     {
54       A[0][0].a[i][i]=1;
55     }
56   for (i=1;i<=m;i++)
57     {
58       A[0][1].a[i][m]=1;
59     }
60   for (i=1;i<m;i++)
61     {
62       A[0][1].a[i+1][i]=1;
63     }
64   for (i=2;i<=9;i++)
65     {
66       A[0][i]=A[0][i-1]*A[0][1];
67     }
68   for (i=1;i<=n;i++)
69     {
70       A[i][0]=A[0][0];
71       A[i][1]=A[i-1][9]*A[i-1][1];
72       for (j=2;j<=9;j++)
73       {
74         A[i][j]=A[i][j-1]*A[i][1];
75       }
76     }
77   f[0].a[1][m]=1;
78   for (i=1;i<=n;i++)
79     {
80       now=A[0][s[i]-'0'];
81       for (j=i-1;j>=0;j--)
82       {
83         f[i]=f[i]+(f[j]*now);
84         if (j) now=A[i-j][s[j]-'0']*now;
85       }
86     }
87   ans=f[n].a[1][m];
88   cout<<ans;
89 }

 

posted @ 2018-03-27 15:50  Z-Y-Y-S  阅读(519)  评论(0编辑  收藏  举报