矩阵乘法。
可以用类似于秦九韶算法,把被取模的数拆开。
如123%m=(((1%m)*10+2)%m*10+3)%m
我们发现对于位数相同的数的计算方法是一样的,想到矩阵乘法。
对于1位的数:
matrix x=10^1 0 0
1 1 0
0 1 1
求1-k的值:[0 1 1]*(x^k)=[a b c] 则a就是答案
对于2位数,只要把10^1换成10^2即可,以此类推。
这个矩阵什么意思呢?
[a b c]中,a是所求,b是当前的数是几(每次都加1),c恒为1(帮助b加1的)
#include <iostream> #include <cmath> #include <cstring> #include <algorithm> #include <cstdlib> #include <cstdio> #define LL long long using namespace std; LL n,mod,a[5],l[5]; struct matrix { LL f[5][5]; }; matrix Mult(matrix a,matrix b) { matrix ans; for (int i=0;i<3;i++) for (int j=0;j<3;j++) ans.f[i][j]=0LL; for (int i=0;i<3;i++) for (int j=0;j<3;j++) for (int k=0;k<3;k++) ans.f[i][j]=(ans.f[i][j]+a.f[i][k]*b.f[k][j]%mod)%mod; return ans; } matrix Pow_mult(LL x,LL n) { matrix base,ans; int f=0; base.f[0][0]=x%mod,base.f[0][1]=base.f[0][2]=base.f[2][0]=base.f[1][2]=0; base.f[1][1]=base.f[1][0]=base.f[2][1]=base.f[2][2]=1; while (n) { if (n&1) { if (!f) ans=base,f=1; else ans=Mult(ans,base); } base=Mult(base,base); n>>=1LL; } return ans; } int main() { scanf("%lld%lld",&n,&mod); LL b=10LL,now=1LL; a[0]=0,a[1]=1,a[2]=1; while (1) { LL la=min(n,now*10LL-1LL); matrix x=Pow_mult(b,la-now+1); for (int i=0;i<3;i++) { l[i]=0LL; for (int j=0;j<3;j++) l[i]=(l[i]+a[j]*x.f[j][i]%mod)%mod; } for (int i=0;i<3;i++) a[i]=l[i]; if (n<b) break; b*=10LL; now=b/10LL; } printf("%lld\n",a[0]); return 0; }
原文地址:http://blog.csdn.net/regina8023/article/details/44014423