标签:bzoj2326 hnoi2011 数学作业 分段矩阵乘法
#include <stdio.h>
int main()
{
puts("转载请注明出处[vmurder]谢谢");
puts("网址:blog.csdn.net/vmurder/article/details/44043191");
}
我们发现
这样我们就对于每个p的阶段都可以构造矩阵加速运算。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define T 3
using namespace std;
long long n,m;
struct MRX
{
long long x[T][T];
}Ini,Std,Trs,E;
inline MRX mul(const MRX &a,const MRX &b)
{
MRX c=E;
int i,j,k;
for(i=0;i<T;i++)for(j=0;j<T;j++)for(k=0;k<T;k++)
c.x[i][j]=(c.x[i][j]+a.x[i][k]*b.x[k][j]%m)%m;
return c;
}
inline MRX power(MRX x,long long p)
{
MRX ret=Std;
while(p)
{
if(p&1)ret=mul(ret,x);
x=mul(x,x),p>>=1;
}
return ret;
}
int main()
{
freopen("test.in","r",stdin);
scanf("%lld%lld",&n,&m);
long long now=10,f=0;
Std.x[0][0]=Std.x[1][1]=Std.x[2][2]=1;
for(;n>=now-now/10&&now<1e18;now*=10)
{
n-=now-now/10;
Trs=Ini=E;
Trs.x[0][0]=now%m;
Trs.x[1][0]=Trs.x[1][1]=1;
Trs.x[2][1]=Trs.x[2][2]=1;
Ini.x[0][0]=f;
Ini.x[0][1]=(now/10)%m;
Ini.x[0][2]=1;
Trs=power(Trs,now-now/10);
f=mul(Ini,Trs).x[0][0];
}
Trs=Ini=E;
Trs.x[0][0]=now%m;
Trs.x[1][0]=Trs.x[1][1]=1;
Trs.x[2][1]=Trs.x[2][2]=1;
Ini.x[0][0]=f;
Ini.x[0][1]=(now/10)%m;
Ini.x[0][2]=1;
Trs=power(Trs,n);
cout<<mul(Ini,Trs).x[0][0]<<endl;
return 0;
}
【BZOJ2326】【HNOI2011】数学作业 分段矩阵乘法
标签:bzoj2326 hnoi2011 数学作业 分段矩阵乘法
原文地址:http://blog.csdn.net/vmurder/article/details/44043191