数学作业(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;
}

 

posted @ 2017-03-29 07:19  karles~  阅读(265)  评论(1编辑  收藏  举报