https://www.lydsy.com/JudgeOnline/problem.php?id=4037
你有一个长度为n的数字串。定义f(S)为将S拆分成若干个1~m的数的和的方案数,比如m=2时,f(4)=5。
你可以将这个数字串分割成若干个数字(允许前导0),将他们加起来,求f,并求和。比如g(123)=f(1+2+3)+f(1+23)+f(12+3)+f(123)。
已知字符串和m后求答案对998244353(7*17*223+1,一个质数)取模后的值。
神仙?(亦或是我从来没见过如此神奇的快速幂于是强行神仙?)
参考:https://blog.csdn.net/H_Anonymity/article/details/78348610
$f$数组一个矩乘快速幂求出,然而并没有卵用。
我们令$f[i]$矩乘所需要的矩阵为$h[i]$。
考虑使用dp求$g$,按位考虑,我们每次加上这位所能带来的贡献。
……或者说,乘上?因为$f(x1+x2)=$初始矩阵$*h[x1]*h[x2]$。
于是令$dp[i]$表示前$i$位的求$g$矩阵,则我们有:
$dp[i]=sum_{j=0}^{i-1}dp[j]*M_j$,其中$M_j=h[j+1$至$i$字符组成的数$]$。
为了求出$M$,我们可以求$f[i][j]$表示$h[i*10^j]$这样我们就能很快捷的求出来了。
听说这个就是神奇的十进制快速幂??
#include<queue> #include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int p=998244353; const int L=505; char s[L]; int n,m; struct matrix{ ll g[6][6]; matrix(){ memset(g,0,sizeof(g)); } inline void one(){ for(int i=0;i<m;i++)g[i][i]=1; } matrix operator *(const matrix &b)const{ matrix c; for(int i=0;i<m;i++) for(int j=0;j<m;j++) for(int k=0;k<m;k++) (c.g[i][j]+=g[i][k]*b.g[k][j]%p)%=p; return c; } matrix operator +(const matrix &b)const{ matrix c; for(int i=0;i<m;i++) for(int j=0;j<m;j++) c.g[i][j]=(g[i][j]+b.g[i][j])%p; return c; } }f[10][L],dp[L]; matrix qpow(matrix x,ll y){ matrix res;res.one(); while(y){ if(y&1)res=res*x; x=x*x;y>>=1; } return res; } void solve(){ f[0][0].one(); for(int i=0;i<m;i++)f[1][0].g[i][0]=1; for(int i=1;i<m;i++)f[1][0].g[i-1][i]=1; for(int i=1;i<=n;i++)f[0][i].one(),f[1][i]=qpow(f[1][i-1],10); for(int i=2;i<=9;i++) for(int j=0;j<=n;j++)f[i][j]=f[i-1][j]*f[1][j]; dp[0].one(); for(int i=1;i<=n;i++){ matrix now=f[s[i]-'0'][0]; for(int j=i-1;j>=0;j--){ dp[i]=dp[i]+dp[j]*now; if(j)now=now*f[s[j]-'0'][i-j]; } } } int main(){ scanf("%s%d",s+1,&m);n=strlen(s+1); solve(); printf("%d ",dp[n].g[0][0]); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++