题解
把矩阵当做DP的值来转移 因为矩阵乘法满足结合律 分配律
然后大力DP就好了
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int M=6;
const int P=998244353;
const int N=505;
int n,m;
struct Mat{
ll a[M][M];
Mat(int t=0){ cl(a); if (t) for (int i=1;i<=m;i++) a[i][i]=1; }
ll *operator[](int x){ return a[x]; }
friend Mat operator * (const Mat &A,const Mat &B){
Mat ret;
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
for (int k=1;k<=m;k++)
(ret[i][j]+=A.a[i][k]*B.a[k][j]%P)%=P;
return ret;
}
friend Mat operator + (const Mat &A,const Mat &B){
Mat ret;
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
ret[i][j]=(A.a[i][j]+B.a[i][j])%P;
return ret;
}
friend Mat Pow(Mat a,int b){
Mat ret(1);
for (;b;b>>=1,a=a*a)
if (b&1)
ret=ret*a;
return ret;
}
}pw[10][N],f[N];
char s[N];
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
scanf("%s%d",s+1,&m); n=strlen(s+1);
for (int i=0;i<=n;i++) pw[0][i]=Mat(1);
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
pw[1][0][i][j]=i==1||i==j+1;
for (int i=1;i<=n;i++) pw[1][i]=Pow(pw[1][i-1],10);
for (int i=2;i<=9;i++) for (int j=0;j<=n;j++) pw[i][j]=pw[i-1][j]*pw[1][j];
f[0]=Mat(1);
for (int i=1;i<=n;i++){
Mat t=pw[s[i]-'0'][0];
for (int j=i-1;~j;j--){
f[i]=f[i]+f[j]*t;
if (j) t=t*pw[s[j]-'0'][i-j];
}
}
printf("%d\n",f[n][1][1]);
return 0;
}
ZJOI那题一样的道理 不过变成了斐波那契的矩阵
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int M=3;
const int P=1000000007;
const int N=1005;
int n,m=2;
struct Mat{
ll a[M][M];
Mat(int t=0){ cl(a); if (t) for (int i=1;i<=m;i++) a[i][i]=1; }
ll *operator[](int x){ return a[x]; }
friend Mat operator * (const Mat &A,const Mat &B){
Mat ret;
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
for (int k=1;k<=m;k++)
(ret[i][j]+=A.a[i][k]*B.a[k][j]%P)%=P;
return ret;
}
friend Mat operator + (const Mat &A,const Mat &B){
Mat ret;
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
ret[i][j]=(A.a[i][j]+B.a[i][j])%P;
return ret;
}
friend Mat Pow(Mat a,int b){
Mat ret(1);
for (;b;b>>=1,a=a*a)
if (b&1)
ret=ret*a;
return ret;
}
}pw[10][N],f[N];
char s[N];
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
scanf("%d%s",&n,s+1); m=2;
for (int i=0;i<=n;i++) pw[0][i]=Mat(1);
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
pw[1][0][i][j]=i==1||i==j+1;
for (int i=1;i<=n;i++) pw[1][i]=Pow(pw[1][i-1],10);
for (int i=2;i<=9;i++) for (int j=0;j<=n;j++) pw[i][j]=pw[i-1][j]*pw[1][j];
f[0][1][1]=1; f[0][1][2]=f[0][2][1]=P-1; f[0][2][2]=2;
for (int i=1;i<=n;i++){
Mat t=pw[s[i]-'0'][0];
for (int j=i-1;~j;j--){
f[i]=f[i]+f[j]*t;
if (j) t=t*pw[s[j]-'0'][i-j];
}
}
printf("%d\n",f[n][1][1]);
return 0;
}