Description
將
1 ~n 的所有自然數連接在一起構成一個新數,求這個數模m 的值,其中n≤1018,m≤109
Tag
矩陣乘法
Solution
構造關於
思路非常顯然不過這裏有一個細節需要注意
我們找出的遞推式是
其中
爲了保證乘的前後始終是一個列矩陣,我們要把矩陣乘在左邊,這樣的話做乘法的時候就要從左邊乘而不是從右邊乘
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
struct matrix
{
LL a[3][3];
matrix(){memset(a,0,sizeof(a));}
void init()
{
memset(a,0,sizeof(a));
for(int i=0;i<3;i++)a[i][i]=1;
}
}g,ans,mrs;
int mod;
LL n,tmp[3];
char c;
template<typename T>
inline void read(T& x)
{
x=0,c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c))x=x*10+c-'0',c=getchar();
}
matrix operator * (matrix a,matrix b)
{
for(int i=0;i<3;i++)for(int j=0;j<3;j++)
{
mrs.a[i][j]=0;
for(int k=0;k<3;k++)mrs.a[i][j]+=a.a[i][k]*b.a[k][j];
mrs.a[i][j]%=mod;
}
return mrs;
}
inline void Pow(matrix A,LL b)
{
while(b)
{
if(b&1)ans=A*ans;//如果寫成ans=ans*A的話就會WA
A=A*A,b>>=1;
}
}
int main()
{
read(n),read(mod),n++;
ans.init();
g.a[0][1]=g.a[1][1]=g.a[1][2]=g.a[2][2]=1;
for(LL now=10,pre=1;;pre=now,now*=10)
{
g.a[0][0]=now%mod;
Pow(g,min(now,n)-pre);
if(now>=n)break;
}
printf("%lld",(ans.a[0][1]+ans.a[0][2])%mod);
return 0;
}