Evanyou Blog 彩带

  题目传送门

数学作业

题目描述

小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题:

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

输入输出格式

输入格式:

 

从文件input.txt中读入数据,输入文件只有一行且为用空格隔开的两个正整数N和M,其中30%的数据满足 1≤N≤1000000 ;100%的数据满足 1≤N≤10^18 且 1≤M≤10^9 .

 

输出格式:

 

输出文件 output.txt 仅包含一个非负整数,表示 Concatenate (1 .. N) Mod M 的值。

 

输入输出样例

输入样例#1: 复制
13 13
输出样例#1: 复制

 4


  分析:明显矩阵加速。代码打出来确实也就是个模板,但是中间矩阵的构造确实非(sang)常(xin)的(bing)难(kuang)。

  首先分析,对于一个k位数x,很明显得到的结果应该是f(x)=f(x-1)*10^k+x;

  那么经过一番简(yao)短(ming)的思考后,可以得到中间矩阵应该是

10^k 0 0
1 1 0
0 1 1

   而初始矩阵应为:

0 1 1
0 0 0
0 0 0

 

  那么剩下的就是矩阵加速模板了~

  Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,mod;
struct Matrix{
    ll a[5][5];
    Matrix(){memset(a,0,sizeof(a));}
    Matrix(ll b[5][5]){memcpy(a,b,sizeof(a));}
    friend Matrix operator * (const Matrix a,const Matrix b){
        Matrix ret;
        for(int i=0;i<=2;i++)
        for(int j=0;j<=2;j++)
        for(int k=0;k<=2;k++)
        ret.a[i][j]=(ret.a[i][j]+(a.a[i][k]*b.a[k][j])%mod)%mod;
        return ret;
    }
}K,T;
int main()
{
    cin>>n>>mod;ll now=0;
    K.a[0][0]=0;K.a[0][1]=1;K.a[0][2]=1;
    for(ll i=10;now<n;i*=10){
        T.a[0][0]=i%mod;T.a[0][1]=0;T.a[0][2]=0;
        T.a[1][0]=1;T.a[1][1]=1;T.a[1][2]=0;
        T.a[2][0]=0;T.a[2][1]=1;T.a[2][2]=1;
        ll ka=min(i-1,n)-now;
        while(ka){
            if(ka&1)K=K*T;
            T=T*T;ka>>=1;}
        now=min(i-1,n);}
    cout<<K.a[0][0];return 0;
}
原文地址:https://www.cnblogs.com/cytus/p/9113776.html