• 数学作业(codevs 2314)


    题目描述 Description

    小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M ,要求计算 Concatenate (1 .. N ) Mod M 的值,其中Concatenate (1 .. N ) 是将所有正整数 1, 2, …, N 顺序连接起来得到的数。例如, N = 13, Concatenate (1 .. N ) = 12345678910111213. 小 C 想了大半天终于意识到这是一道不可能手算出来的题目,于是他只好向你求助,希望 你能编写一个程序帮他解决这个问题。

    输入描述 Input Description

    只有一行 为用空格隔开的两个正整数 N 和 M

    输出描述 Output Description

    仅包含一个非负整数,表示 Concatenate (1 .. N ) Mod M 的值

    样例输入 Sample Input

    13 13

    样例输出 Sample Output

    4

    数据范围及提示 Data Size & Hint

    其中 30%的数据满足1≤ N ≤1000000;100%的数据满足1≤ N ≤1018且1≤ M ≤109

    /*
        矩阵乘法
        按位进行计算,公式很好推。
        矩阵乘法写得少,导致代码特别难看。
    */
    #include<cstdio>
    #include<iostream>
    #define lon long long
    using namespace std;
    lon A[4][4],B[4][4],n,mod,ans;
    void mul(lon a[4][4],lon b[4][4],lon c[4][4]){
        lon tmp[4][4]={0};
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
                for(int k=1;k<=3;k++)
                    tmp[i][j]+=(a[i][k]*b[k][j])%mod,tmp[i][j]%=mod;
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
                c[i][j]=tmp[i][j];
    }
    void mi(lon a[4][4],lon b){
        lon base[4][4]={0},r[4][4]={0};
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
                base[i][j]=a[i][j];
        for(int i=1;i<=3;i++) r[i][i]=1;
        while(b){
            if(b&1) mul(base,r,r);
            mul(base,base,base);
            b>>=1;
        }
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
                a[i][j]=r[i][j];
    }
    lon pow10(int x){
        lon ans=1;
        for(int i=1;i<=x;i++) ans*=10;
        return ans;
    }
    void init(){
        int ans=0;
        for(int i=1;i<=n;i++)
            ans=ans*10+i,ans%=mod;
        cout<<ans;
    }
    int main(){
        cin>>n>>mod;
        if(n<10) {init();return 0;}
        ans=123456789;
        for(int i=2;i<=18;i++){
            A[1][1]=ans;A[1][2]=pow10(i-1)%mod;A[1][3]=1;
            A[2][1]=A[2][2]=A[2][3]=0;
            A[3][1]=A[3][2]=A[3][3]=0;
            B[1][1]=pow10(i)%mod;B[1][2]=0;B[1][3]=0;
            B[2][1]=1;B[2][2]=1;B[2][3]=0;
            B[3][1]=0;B[3][2]=1;B[3][3]=1;
            lon ci=min(pow10(i)-1,n)-pow10(i-1)+1;
            if(ci<0) break;
            mi(B,ci);
            mul(A,B,A);
            ans=A[1][1]%mod;
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    linux unzip
    ASP.NetViewState的实现方案
    周鸿袆:从程序员创业谈起
    程序员不是神,心态决定一切
    35岁以前成功的12条黄金法则
    Web的系统测试方法 (转载)
    Assembly反射机制错误解决之道
    利用ViewState保存Html控件状态
    触发器与@@IDENTITY的
    基于SQL Server 2005新特性的分页存储过程
  • 原文地址:https://www.cnblogs.com/harden/p/6637841.html
Copyright © 2020-2023  润新知