BZOJ 2326 [HNOI2011]數學作業
阿新 • • 發佈:2018-06-17
KS sca hnoi tip sizeof 優化 ++ cout struct
這種題我都WA了一個小時我是不是沒救了
首先寫出遞推式$f[i]=f[i-1] \times 10^{len_{i}} + i $
然後按照\(len_{i}\)分層用矩陣乘法優化即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cassert>
using namespace std;
long long n;
long long ans=0;
int mm;
struct Matrix{
long long z[4][4];
Matrix(){
memset(z,0 ,sizeof(z));
}
void Clr(){
memset(z,0,sizeof(z));
}
void MakeE(){
memset(z,0,sizeof(z));
z[1][1]=z[2][2]=z[3][3]=1;
}
};
Matrix Multiply(Matrix A,Matrix B){
Matrix C;
for(int i=1;i<=3;++i){
for(int j=1;j<=3;++j){
for(int k=1 ;k<=3;++k){
C.z[i][j]=(C.z[i][j]+A.z[i][k]*B.z[k][j])%mm;
}
}
}
return C;
}
Matrix Ksm(Matrix a,long long p){
Matrix ret;
ret.MakeE();
for(;p;p>>=1,a=Multiply(a,a)){
if(p&1)ret=Multiply(ret,a);
}
return ret;
}
int main(){
scanf("%lld%d",&n,&mm);
int len=0;
long long x=n;
while(x){
x/=10;++len;
}
long long now=1;
for(int i=1;i<=len;++i){
long long k;
if(i==len){
k=n-now+1;
}else{
k=now*10-now;
}
Matrix a;
a.z[1][1]=(now*10)%mm;
a.z[1][2]=1;
a.z[1][3]=1;
a.z[2][2]=1;
a.z[2][3]=1;
a.z[3][3]=1;
Matrix ret=Ksm(a,k);
ans=(ans*ret.z[1][1]%mm+(now-1+mm)%mm*ret.z[1][2]%mm+ret.z[1][3])%mm;
now=now*10;
}
cout<<ans<<endl;
return 0;
}
BZOJ 2326 [HNOI2011]數學作業