BZOJ 2326 [HNOI2011]数学作业

这种题我都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;
}

猜你喜欢

转载自www.cnblogs.com/zzyer/p/9192978.html