• bzoj2326: [HNOI2011]数学作业


    矩阵乘法.

                                          10^k,0,0

    (f[i+1],i+1,1) = (f[i],i,1)  ( 1,     1,0 )

                                           1.     1,0)

    k为(i+1)的位数。这点很重要,所以每回都是算到999…9,然后k就会+1。所以题目中的l和r都是实际值+1。(需要yy一下)。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    unsigned long long n,mod;
    
    struct Matrix {
        long long a[3][3];
        
        long long* operator [] (int x) {
            return a[x];
        }
        
        Matrix operator* (Matrix b) {
            Matrix res;
            for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
            for(int k=0;k<3;k++)
            res[i][j]=(res[i][j]+a[i][k]*b[k][j])%mod;
            return res;    
        }
        
        Matrix operator ^ (long long e) {
            Matrix res(1),tmp=*this;
            while(e) {
                if(e&1) res=res*tmp;
                tmp=tmp*tmp;
                e>>=1;
            }
            return res;
        }
        
        void build(long long x) {
            memset(a,0,sizeof(a));
            a[0][0]=x%mod;
            for(int i=1;i<3;i++)
            for(int j=0;j<=i;j++)
                a[i][j]=1;
        }
        
        Matrix(long long x=0) {
            memset(a,0,sizeof(a));
            for(int i=0;i<3;i++) a[i][i]=x;    
        }
        
    }cur;
    
    struct Vector {
        long long a[3];    
        
        long long& operator [] (int x) {
            return a[x];
        }
        
        Vector operator * (Matrix b) {
            Vector res;
            for(int i=0;i<3;i++) 
            for(int k=0;k<3;k++) 
                res[i]=(res[i]+a[k]*b[k][i])%mod;
            return res;
        }
        
        void build() {
            memset(a,0,sizeof(a));    
            a[2]=1;
        }
        
        Vector() {
            memset(a,0,sizeof(a));
        }
    }res;
    
    int main() {
        scanf("%lld%lld",&n,&mod);
        res.build();
        long long l,r;
        for(l=1,r=10;r<=n;l=r,r=l*10) {
            cur.build(r);
            res=res*(cur^(r-l));
        }
        cur.build(r);
        res=res*(cur^(n-l+1));
        printf("%lld
    ",res[0]);
        return 0;
    }
  • 相关阅读:
    第5课.异步通知
    第4课.poll机制
    第3课.Linux异常处理体系结构
    第2课.字符设备驱动程序的开发
    第1课.Linux驱动的概述
    [Linux驱动]字符设备驱动学习笔记(二)———实例
    [linux驱动]linux块设备学习笔记(三)——程序设计
    [Linux驱动]字符设备驱动学习笔记(一)
    [linux驱动]proc学习笔记(一)
    [linux驱动][Linux内存]DMA学习笔记一
  • 原文地址:https://www.cnblogs.com/invoid/p/5526081.html
Copyright © 2020-2023  润新知