P3216 [HNOI2011]数学作业

题目大意

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

题目分析

显然矩阵快速幂。

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
ull n,m;
struct Mat{
    ull a[5][5];
    Mat(){memset(a,0,sizeof(a));}
    ull*operator[](int x){return a[x];}
    void init(){for(int i=0;i<3;i++)a[i][i]=1;}
    Mat operator*(Mat b){
        Mat c;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                for(int k=0;k<3;k++)
                    c[i][j]=(c[i][j]+a[i][k]*b[k][j])%m;
        return c;
    }
    Mat operator^(ull cnt){
        Mat ret,mul=*this;ret.init();
        for(;cnt;cnt>>=1,mul=mul*mul)if(cnt&1)ret=ret*mul;
        return ret;
    }
};
int main(){
    cin>>n>>m;
    ull now=1;
    Mat Ans,mul;
    Ans[0][0]=0;Ans[0][1]=1;Ans[0][2]=1;
    while(1){
        mul[0][0]=now*10%m;mul[0][1]=0;mul[0][2]=0;
        mul[1][0]=1;mul[1][1]=1;mul[1][2]=0;
        mul[2][0]=0;mul[2][1]=1;mul[2][2]=1;
        if(now*10<=n){
            mul=mul^(now*9);
            Ans=Ans*mul;
        }
        else{
            mul=mul^(n-now+1);
            Ans=Ans*mul;break;
        }
        now*=10;
    }
    cout<<Ans[0][0]%m<<"\n";
}
/*
13 13
12345678910 1000000000

             [10^k,0,0]
[num,next,1]*[1   ,1,0]
             [0   ,1,1]
*/

转载于:https://www.cnblogs.com/Trrui/p/9686224.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值