bzoj2326: [HNOI2011]数学作业
矩阵乘法.
10^k,0,0
(f[i+1],i+1,1) = (f[i],i,1) ( 1, 1,0 )
1. 1,0)
k为(i+1)的位数。这点很重要,所以每回都是算到999…9,然后k就会+1。所以题目中的l和r都是实际值+1。(需要yy一下)。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; unsigned long long n,mod; struct Matrix { long long a[3][3]; long long* operator [] (int x) { return a[x]; } Matrix operator* (Matrix b) { Matrix res; for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++) res[i][j]=(res[i][j]+a[i][k]*b[k][j])%mod; return res; } Matrix operator ^ (long long e) { Matrix res(1),tmp=*this; while(e) { if(e&1) res=res*tmp; tmp=tmp*tmp; e>>=1; } return res; } void build(long long x) { memset(a,0,sizeof(a)); a[0][0]=x%mod; for(int i=1;i<3;i++) for(int j=0;j<=i;j++) a[i][j]=1; } Matrix(long long x=0) { memset(a,0,sizeof(a)); for(int i=0;i<3;i++) a[i][i]=x; } }cur; struct Vector { long long a[3]; long long& operator [] (int x) { return a[x]; } Vector operator * (Matrix b) { Vector res; for(int i=0;i<3;i++) for(int k=0;k<3;k++) res[i]=(res[i]+a[k]*b[k][i])%mod; return res; } void build() { memset(a,0,sizeof(a)); a[2]=1; } Vector() { memset(a,0,sizeof(a)); } }res; int main() { scanf("%lld%lld",&n,&mod); res.build(); long long l,r; for(l=1,r=10;r<=n;l=r,r=l*10) { cur.build(r); res=res*(cur^(r-l)); } cur.build(r); res=res*(cur^(n-l+1)); printf("%lld\n",res[0]); return 0; }