来自FallDream的博客,未经允许,请勿转载,谢谢。
一个数接在后面的时候我们都可以看作乘以10的对应次方再加上这个数,所以考虑构造关于f(x),x矩阵,每次x还要加1,所以变成
(f[x] ) (10^k) ( 1 ) ( 1 ) (f[x+1])
( x ) * ( 0 ) ( 1 ) ( 1 ) = ( x+1 )
( 1 ) ( 0 ) ( 0 ) ( 1 ) ( 1 )
对于不同的k分开处理
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; inline ll read() { ll x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } int mod,pw[19]; ll n; struct Matrix { int s[4][4],r,c; Matrix(){memset(s,0,sizeof(s));} Matrix(int y) { memset(s,0,sizeof(s));r=c=3; s[1][1]=pw[y];s[1][2]=s[1][3]=1; s[2][3]=s[2][2]=s[3][3]=1; } Matrix(int a,int b) { memset(s,0,sizeof(s));r=3;c=1; s[1][1]=a;s[2][1]=b;s[3][1]=1; } Matrix operator*(Matrix b) { Matrix d;d.r=r;d.c=b.c; for(int i=1;i<=r;i++) for(int j=1;j<=c;j++) for(int k=1;k<=b.c;k++) d.s[i][k]=(d.s[i][k]+1LL*s[i][j]*b.s[j][k])%mod; return d; } }a(0,0); void solve(int k,ll c) { Matrix b(k); for(;c;c>>=1,b=b*b) if(c&1) a=b*a; } int main() { n=read();mod=read(); pw[1]=10%mod; for(int i=2;i<=18;i++) pw[i]=1LL*pw[i-1]*10%mod; for(ll i=9,last=0,j=1;n>last;++j,last=i,i=i*10+9) solve(j,min(i,n)-last); printf("%d ",a.s[1][1]); return 0; }