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×2^23+1,一個質數)取模後的值。
Solution
容易知道f的遞推式,
但是
預處理初矩陣
注意卡常。
Code
#include <bits/stdc++.h>
#define maxn 510
using namespace std;
typedef long long ll;
const int mod = 998244353;
char s[maxn];
int a[maxn], m, n;
struct Matrix{
ll a[5][5];
void clear(){memset(a, 0, sizeof a);}
void set(){clear();for(int i = 0; i < m; i ++)a[i][i] = 1;}
}A;
Matrix operator*(const Matrix& a, const Matrix& b){
Matrix c;c.clear();
for(int i = 0; i < m; i ++)
for(int j = 0; j < m; j ++){
for(int k = 0; k < m; k ++)
c.a[i][j] += a.a[i][k] * b.a[k][j];
c.a[i][j] %= mod;
}
return c;
}
void operator += (Matrix& a, const Matrix& b){
for(int i = 0; i < m; i ++)
for(int j = 0; j < m; j ++){
a.a[i][j] += b.a[i][j];
if(a.a[i][j] >= mod)a.a[i][j] -= mod;
}
}
Matrix dp[maxn], num[maxn][10];
Matrix power(Matrix ret, int k){
Matrix ans;ans.set();
while(k){
if(k & 1)ans = ans * ret;
k >>= 1;
ret = ret * ret;
}
return ans;
}
int main(){
scanf("%s%d", s+1, &m);
n = strlen(s+1);
for(int i = 1; i <= n; i ++)a[i] = s[i] ^ 48;
for(int i = 0; i < m; i ++)A.a[i][0] = 1;
for(int i = 0; i < m-1; i ++)A.a[i][i+1] = 1;
for(int i = 1; i <= n; i ++){
num[i][0].set();
for(int j = 1; j < 10; j ++)
num[i][j] = num[i][j-1] * A;
A = power(A, 10);
}
dp[0].set();
for(int i = 1; i <= n; i ++){
A.set();
for(int j = i-1; j >= 0; j --){
A = num[i-j][a[j+1]] * A;
dp[i] += dp[j] * A;
}
}
printf("%lld\n", dp[n].a[0][0] % mod);
return 0;
}