codevs 2314 数学作业

2314 数学作业

 

2011年省队选拔赛湖南

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
题目描述 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<cstring>
#include<algorithm>
using namespace std;
typedef int matrix[3][3];
typedef long long ll;
ll N;
int MOD;
matrix mat,Q,tmp;
void Init_matrix(){
    memset(mat,0,sizeof(mat));
    mat[0][1]=mat[0][2]=mat[1][1]=mat[1][2]=mat[2][2]=1;
    memset(Q,0,sizeof(Q));
    for(int i=0;i<3;i++)Q[i][i]=1;
}
void Mul(matrix &a,matrix &b){
    memset(tmp,0,sizeof(tmp));
    for(int i=0;i<3;i++)
        for(int k=0;k<3;k++)
            for(int j=0;j<3;j++)
                if((tmp[i][j]+=ll(a[i][k])*b[k][j]%MOD)>=MOD)
                    tmp[i][j]-=MOD;
    memcpy(a,tmp,sizeof(a));
}
void Power(matrix &a,matrix &b,ll k){
    while(k){if(k&1)Mul(a,b);k>>=1;Mul(b,b);}
}
int main(){
    scanf("%lld%d",&N,&MOD);
    int len=0,B=0,C=0;
    ll p=1;
    for(ll t=N;t;t/=10,len++);
    for(int i=1;i<len;i++){
        Init_matrix();
        mat[0][0]=(p=p*10)%MOD;
        Power(Q,mat,p-p/10);
        B=(ll(B)*Q[0][0]%MOD+ll(C)*Q[0][1]%MOD+Q[0][2])%MOD;
        C=((p%MOD)-1+MOD)%MOD;
    }
    Init_matrix();
    mat[0][0]=p*10%MOD;
    Power(Q,mat,N-p+1);
    B=(ll(B)*Q[0][0]%MOD+ll(C)*Q[0][1]%MOD+Q[0][2])%MOD;
    printf("%d
",B);
    return 0;
} 
原文地址:https://www.cnblogs.com/thmyl/p/6941733.html