很容易得到递推式
f[i]=f[i−1]∗10k+i
(10k−1<=i<10k)
数据范围达到
1018
,所以很容易想到用矩阵优化。
构造矩阵:
(f[i]i1)∗⎛⎝⎜10k11011001⎞⎠⎟
然后分段开开心心的分段矩乘啦。注意边界。
【代码】
#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 10005
using namespace std;
typedef long long ll;
ll read()
{
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
class matrix{
public:
int x,y;
ll v[4][4];
}a,b,s;
ll n,tmp=1;
int mod,m;
ll Qmul(ll x,ll y)
{
ll rtn=0;
while(y)
{
if(y&1) rtn=(rtn+x)%mod;
x=(x+x)%mod;y>>=1;
}
return rtn;
}
matrix Matrix_Mul(matrix aa,matrix bb)
{
matrix rtn;
rtn.x=aa.x,rtn.y=bb.y;
for(int i=1;i<=aa.x;i++)
for(int j=1;j<=aa.y;j++)
{
rtn.v[i][j]=0;
for(int k=1;k<=bb.y;k++)
rtn.v[i][j]=(rtn.v[i][j]+Qmul(aa.v[i][k],bb.v[k][j]))%mod;
}
return rtn;
}
void Matrix_Pow(ll num)
{
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++) s.v[i][j]=b.v[i][j];
s.x=s.y=3;
while(num)
{
if(num&1) a=Matrix_Mul(a,s);
s=Matrix_Mul(s,s);num>>=1;
}
}
int main()
{
n=read(),mod=read();
a.v[1][3]=1;a.x=1,a.y=3;
b.x=b.y=3;
for(int i=1;i<=3;i++)
for(int j=1;j<=i;j++) b.v[i][j]=1;
for(;;)
{
b.v[1][1]*=10;
if(tmp*10-1>=n)
{
Matrix_Pow(n-tmp+1);
break;
}
Matrix_Pow(tmp*10-tmp);tmp*=10;
}
printf("%lld\n",a.v[1][1]);
return 0;
}