• 【bzoj】2326 [HNOI2011]数学作业


    【题意】给定n和m,求1~n从高位到低位连接%m的结果。n=11时,ans=1234567891011%m。n<=10^18,m<=10^9。

    【算法】递推+矩阵快速幂

    【题解】

    考虑枚举位数个数k,对于不同的k单独递推,设f[i]表示1~i的答案,则有:

    $$f_n=f_{n-1}*10^k+i$$

    转化为矩阵递推式,则有:

    $$egin{vmatrix}10^k & 1 & 1\ 0 & 1 & 1\0 & 0 & 1end{vmatrix} imes egin{vmatrix}f_n \ n\1 end{vmatrix}=egin{vmatrix}f_{n+1}\n+1\1end{vmatrix}$$

    转化为幂形式,则有:

    $$egin{vmatrix}10^k & 1 & 1\ 0 & 1 & 1\0 & 0 & 1end{vmatrix}^n imes egin{vmatrix}f_i \ i\1 end{vmatrix}=egin{vmatrix}f_{i+n}\i+n\1end{vmatrix}$$

    分段进行矩阵快速幂即可。

    注意读入的n是long long。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=3;
    int c[N][N],ANS[N][N],A[N][N],m;
    ll n;///
    void multply(int a[N][N],int b[N][N]){
        for(int i=0;i<=2;i++){
            for(int j=0;j<=2;j++){
                c[i][j]=0;
                for(int k=0;k<=2;k++){
                    c[i][j]=(c[i][j]+1ll*a[i][k]*b[k][j]%m)%m;
                }
            }
        }
        for(int i=0;i<=2;i++)for(int j=0;j<=2;j++)b[i][j]=c[i][j];
    }
    void solve(ll p,int &f,int x,int k){
        memset(A,0,sizeof(A));
        A[0][1]=A[0][2]=A[1][1]=A[1][2]=A[2][2]=1;A[0][0]=k;
        ANS[0][0]=f;ANS[1][0]=x%m;ANS[2][0]=1;
        while(p){
            if(p&1)multply(A,ANS);
            multply(A,A);
            p>>=1;
        }
        f=ANS[0][0];
    }
    int main(){
        scanf("%lld%d",&n,&m);
        ll x=0,y=9;
        int k=10%m,ans=0;
        while(x+y<n){
            solve(y,ans,x%m,k);//
            x+=y;y*=10;k=1ll*k*10%m;
        }
        solve(n-x,ans,x%m,k);
        printf("%d",ans%m);
        return 0;
    }
    View Code
  • 相关阅读:
    spring mvc valid
    记录一次springmvc 404
    用到的 git 命令
    tomcat java.lang.OutOfMemoryError: PermGen space
    angularjs 表单验证 和 页面初始化闪烁
    在jsp中 EL表达式不生效
    关于jsp中使用jstl的问题
    块级元素,内联元素和定位
    java学习第4天
    STL 常用集合算法
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6580039.html
Copyright © 2020-2023  润新知