Description
Solution
很容易想到拆式子变成统计合法数字的和,以及合法数字的平方和
记
f
i
,
j
f_{i,j}
fi,j表示长度为i,每一位和为j的所有数字的和,
g
i
,
j
g_{i,j}
gi,j平方和,
h
i
,
j
h_{i,j}
hi,j数量
写一下转移可以发现i没有用,这样就有60’
看一下数据可以发现矩阵乘法,这样就有100’
难点在于搞出矩阵。。
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#define rep(i,st,ed) for (register int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
const int MOD=1000003;
const int ny2=500002;
struct Mat {
int r[31][31];
Mat() {fill(r,0);}
int* operator [](int x) {return r[x];}
Mat operator *(Mat B) const {
Mat A=*this,C;
rep(i,1,29) rep(j,1,29) {
rep(k,1,29) C[i][j]=C[i][j]+1LL*A[i][k]*B[k][j]%MOD;
C[i][j]%=MOD;
}
return C;
}
Mat operator ^(long long x) {
Mat C=*this,A=*this; x--;
for (;x;x>>=1) {
if (x&1) C=C*A;
A=A*A;
}
return C;
}
} G,A;
void debug(Mat A) {
rep(i,1,29) {
rep(j,1,29) printf("%d ", A[i][j]);
puts("");
}
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
rep(i,2,9) G[i-1][i]=1;
rep(i,1,9) G[i][1]=1;
rep(i,2,9) G[i+9-1][i+9]=1;
rep(i,1,9) G[i+9][10]=10;
rep(i,1,9) G[i][10]=i;
G[28][28]=G[10][28]=1;
rep(i,2,9) G[i+18-1][i+18]=1;
rep(i,1,9) G[i+18][19]=100;
rep(i,1,9) G[i][19]=i*i;
rep(i,1,9) G[i+9][19]=20*i;
G[29][29]=G[19][29]=1;
// debug(G);
long long m;
scanf("%lld",&m); A=G^(m+1);
// debug(A);
long long ans1=A[1][28],ans2=A[1][29];
// printf("%d %d\n", ans1,ans2);
long long ans=1LL*ans1*ans1%MOD-ans2;
ans=(ans%MOD+MOD)%MOD;
ans=ans*ny2%MOD;
printf("%lld\n", ans);
return 0;
}