zoukankan      html  css  js  c++  java
  • 【BZOJ2326】数学作业(HNOI2011)-递推+矩阵快速幂

    测试地址:数学作业
    做法:本题需要用到递推+矩阵快速幂。
    f(i)Concatenate(i)m取模后的结果,很快能得到一个递推式:
    f(i+1)=f(i)×10k+i+1
    注意到所需的信息:f(i)i+1,它们是可以同时递推的,所以我们就可以构造一个转移矩阵,使得能从向量{f(i),i+1,1}转移到{f(i+1),i+2,1},应该很容易构造,实在不会请看代码。而k的话最大也就19,因此我们只需对于k=1,2,...的每段都求一遍矩阵快速幂即可,时间复杂度为O(log2n)
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ll;
    ll n,mod;
    struct matrix
    {
        ll mat[3][3];
    }M[110],S;
    
    void mult(matrix &S,matrix A,matrix B)
    {
        memset(S.mat,0,sizeof(S.mat));
        for(int i=0;i<=2;i++)
            for(int j=0;j<=2;j++)
                for(int k=0;k<=2;k++)
                    S.mat[i][j]=(S.mat[i][j]+A.mat[i][k]*B.mat[k][j])%mod;
    }
    
    void power(matrix &S,ll p)
    {
        int i=0;
        while(p)
        {
            if (p&1) mult(S,M[i],S);
            i++;p>>=1;
        }
    }
    
    int main()
    {
        scanf("%llu%llu",&n,&mod);
    
        ll now=0,limit=10;
    
        memset(S.mat,0,sizeof(S.mat));
        S.mat[0][0]=S.mat[1][1]=S.mat[2][2]=1;
    
        while(now<n)
        {
            ll p;
    
            if (limit<=n) p=limit-1-now;
            else p=n-now;
    
            M[0].mat[0][0]=limit%mod,M[0].mat[0][1]=1,M[0].mat[0][2]=0;
            M[0].mat[1][0]=0,M[0].mat[1][1]=1,M[0].mat[1][2]=1;
            M[0].mat[2][0]=0,M[0].mat[2][1]=0,M[0].mat[2][2]=1;
            for(int i=1;i<=70;i++)
                mult(M[i],M[i-1],M[i-1]);
    
            power(S,p);
    
            now=limit-1;
            limit*=10;
        }
        printf("%llu",(S.mat[0][1]+S.mat[0][2])%mod);
    
        return 0;
    }
  • 相关阅读:
    Mego(02)
    Mego(01)
    ThoughtWorks(中国)程序员读书雷达 —— 书籍下载整理
    Spring源码编译一次性通过&遇到的坑解决方法
    Elasticsearch怎么修改索引字段类型?
    Flume 自定义拦截器 多行读取日志+截断
    用Hibernate框架把hql生成可执行的sql语句-Oracle方言
    深入浅出SQL Server中的死锁 [转于CareySon]
    第一次迭代随笔
    结对编程代码分析
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793336.html
Copyright © 2011-2022 走看看