某次noip模拟赛遇见了,打完后发现它,二话不说就A了。
其实就是简单的矩阵快速幂,构造矩阵
{10^a,0,0}
{1, 1,0}
{0, 1,1}
在乘一乘,处理细节,就好了。
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
using namespace std;
long long n,tmp,k,mod;
long long f[20];
struct matrix{
int h;
int l;
long long data[5][5];
};
matrix a,b,c;
matrix multiply(matrix A,matrix B)
{
matrix ans;
ans.h=A.h,ans.l=B.l;
for(int i=1;i<=ans.h;i++)
for(int j=1;j<=ans.l;j++)
ans.data[i][j]=0;
for(int i=1;i<=ans.h;i++)
for(int j=1;j<=ans.l;j++)
for(int k=1;k<=A.l;k++)
ans.data[i][j]=(ans.data[i][j]+A.data[i][k]*B.data[k][j])%mod;
return ans;
}
void write(matrix A)
{
for(int i=1;i<=A.h;i++)
{
for(int j=1;j<=A.l;j++)
cout<<A.data[i][j]<<" ";
cout<<endl;
}
}
matrix ksm(matrix A,long long B)
{
matrix ans;
ans.h=A.h,ans.l=A.l;
for(int i=1;i<=ans.h;i++)
for(int j=1;j<=ans.l;j++)
ans.data[i][j]=(i==j);
while(B)
{
if(B&1)ans=multiply(ans,A);
B>>=1;
A=multiply(A,A);
}
return ans;
}
int main()
{
//freopen("math.in","r",stdin);
//freopen("math.out","w",stdout);
cin>>n>>mod;
if(n<=100000)
{
for(int i=1;i<=min((long long)9,n);i++)
tmp=(tmp*10+i)%mod;
for(int i=10;i<=min((long long)99,n);i++)
tmp=(tmp*100+i)%mod;
for(int i=100;i<=min((long long)999,n);i++)
tmp=(tmp*1000+i)%mod;
for(int i=1000;i<=min((long long)9999,n);i++)
tmp=(tmp*10000+i)%mod;
for(int i=10000;i<=min((long long)99999,n);i++)
tmp=(tmp*100000+i)%mod;
for(int i=100000;i<=min((long long)999999,n);i++)
tmp=(tmp*1000000+i)%mod;
cout<<tmp%mod;
return 0;
}
f[0]=1;
for(int i=1;i<=18;i++)f[i]=f[i-1]*10;
a.h=1,a.l=3,a.data[1][1]=0;a.data[1][2]=1;a.data[1][3]=1;
b.h=3,b.l=3,b.data[1][1]=1;b.data[1][2]=0;b.data[1][3]=0;
b.data[2][1]=1;b.data[2][2]=1;b.data[2][3]=0;
b.data[3][1]=0;b.data[3][2]=1;b.data[3][3]=1;
for(int i=1;n>0;i++)
{
b.data[1][1]=f[i]%mod;
if(f[i]==0)k=n;
else k=min(n,f[i]-f[i-1]);
c=ksm(b,k);
a=multiply(a,c);
n-=k;
}
cout<<a.data[1][1];
return 0;
}