1. 程式人生 > >BZOJ 2326 [HNOI2011]數學作業

BZOJ 2326 [HNOI2011]數學作業

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]數學作業