我会告诉你们我发这题解是骗积分?
哎真是弱。。囧。。
既然n已经大到了10^18。那我们果断考虑矩阵。
开始构造矩阵。
因为k是会变得。那根据位数分类算。k=1:n=1~9;k=2:n=10~99……
n也是会变得所以放进矩阵好了。
那我们得到这么个玩意儿:
对于同一个k得到:
最后上矩阵乘法和快速幂。( 我会告诉你们我矩阵乘法写萎了死调还没发现?)
贴代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef unsigned long long ll;
struct matrix{
int r,c;
ll num[4][4];
matrix(){
memset(num,0,sizeof(num));
}
}a,b,ans;
ll n,m,p10[20];
inline ll mul(ll a,ll b){
ll ans=0;
while(b){
if(b&1)ans=(ans+a)%m;
b>>=1;
a=(a+a)%m;
}
return ans;
}
inline void print(matrix a){
printf("-----------------\n");
for(int i=1;i<=a.r;i++){
for(int j=1;j<=a.c;j++)printf("%d ",a.num[i][j]);
printf("\n");
}
printf("-----------------\n");
}
matrix operator * (const matrix &a,const matrix &b){
matrix c;
c.r=a.r;
c.c=b.c;
for(int i=1;i<=a.r;i++)
for(int j=1;j<=b.c;j++)
for(int k=1;k<=a.c;k++)
c.num[i][j]=(c.num[i][j]+mul(a.num[i][k],b.num[k][j]))%m;
return c;
}
matrix operator ^ (matrix a,ll b){
matrix ans;
ans.r=ans.c=a.c;
for(int i=1;i<=ans.r;i++)ans.num[i][i]=1;
while(b){
if(b&1)ans=ans*a;
b>>=1;
a=a*a;
}
return ans;
}
inline int getlen(ll n){
int ret=0;
while(n) ret++,n/=10;
return ret;
}
int main()
{
p10[0]=1;
for(int i=1;i<19;i++)p10[i]=10*p10[i-1];
cin>>n>>m;
int len=getlen(n);
a.r=3,a.c=1;
a.num[1][1]=a.num[2][1]=0;a.num[3][1]=1;
b.r=b.c=3;
for(int i=1;i<len;i++){
b.num[1][1]=p10[i];b.num[1][2]=b.num[1][3]=b.num[2][2]=b.num[2][3]=b.num[3][3]=1;
b.num[2][1]=b.num[3][1]=b.num[3][2]=0;
a=(b^(9*p10[i-1]))*a;
}
b.num[1][1]=p10[len];b.num[1][2]=b.num[1][3]=b.num[2][2]=b.num[2][3]=b.num[3][3]=1;
b.num[2][1]=b.num[3][1]=b.num[3][2]=0;
a=(b^(n-p10[len-1]+1))*a;
cout<<a.num[1][1]<<endl;
return 0;
}