矩阵快速幂
[f(n) n 1]=[f(n-1) n-1 1]*(10^len 0 0)
(1 1 0)
(1 1 1)
然后细节扣一扣,我是把1~9分开算,因为比后面统一位数做的矩乘次数少1(因为1已知)
/**************************************************************
Problem: 2326
User: syh0313
Language: C++
Result: Accepted
Time:28 ms
Memory:1292 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
using
namespace
std;
const
int
N=3;
long
long
n,mo,ans,now[N][N],f,num,p[21];
int
len;
long
long
tmp[N][N];
void
multi(
long
long
a[][N],
long
long
b[][N],
int
n)
{
memset
(tmp,0,
sizeof
tmp);
for
(
int
i=0;i<n;i++)
for
(
int
j=0;j<n;j++)
for
(
int
k=0;k<n;k++)
tmp[i][j]=(tmp[i][j]+(a[i][k]%mo*(b[k][j]%mo))%mo)%mo;
for
(
int
i=0;i<n;i++)
for
(
int
j=0;j<n;j++)
a[i][j]=tmp[i][j];
}
long
long
res[N][N];
void
Pow(
long
long
a[][N],
long
long
n)
{
memset
(res,0,
sizeof
res);
for
(
int
i=0;i<3;i++) res[i][i]=1;
while
(n)
{
if
(n&1)
multi(res,a,3);
multi(a,a,3);
n>>=1;
}
}
int
main()
{
scanf
(
"%lld%lld"
,&n,&mo);
p[1]=1;
for
(
int
i=2;i<=20;i++) p[i]=p[i-1]*10;
long
long
k=n;
while
(k) {len++; k/=10;}
f=1; num=1;
if
(n<=9)
{
now[0][0]=10; now[0][1]=0; now[0][2]=0;
now[1][0]=1; now[1][1]=1; now[1][2]=0;
now[2][0]=1; now[2][1]=1; now[2][2]=1;
Pow(now,n-1);
ans=(f*res[0][0]%mo+num*res[1][0]%mo+res[2][0])%mo;
printf
(
"%lld\n"
,ans);
return
0;
}
now[0][0]=10; now[0][1]=0; now[0][2]=0;
now[1][0]=1; now[1][1]=1; now[1][2]=0;
now[2][0]=1; now[2][1]=1; now[2][2]=1;
Pow(now,8);
long
long
aa=(f*res[0][0]%mo+num*res[1][0]%mo+res[2][0])%mo;
long
long
bb=(f*res[0][1]%mo+num*res[1][1]%mo+res[2][1])%mo;
f=aa; num=bb;
for
(
int
i=2;i<len;i++)
{
now[0][0]=p[i+1]; now[0][1]=0; now[0][2]=0;
now[1][0]=1; now[1][1]=1; now[1][2]=0;
now[2][0]=1; now[2][1]=1; now[2][2]=1;
Pow(now,p[i+1]-p[i]);
aa=(f*res[0][0]%mo+num*res[1][0]%mo+res[2][0])%mo;
bb=(f*res[0][1]%mo+num*res[1][1]%mo+res[2][1])%mo;
f=aa; num=bb;
//puts("laaaaa");
}
//rintf("lalal %lld\n",f);
now[0][0]=p[len+1]; now[0][1]=0; now[0][2]=0;
now[1][0]=1; now[1][1]=1; now[1][2]=0;
now[2][0]=1; now[2][1]=1; now[2][2]=1;
Pow(now,n-p[len]+1);
//puts("lalaa");
ans=(f*res[0][0]%mo+num*res[1][0]%mo+res[2][0])%mo;
printf
(
"%lld\n"
,ans);
return
0;
}