洛谷P3216 [HNOI2011] 数学作业 [矩阵加速,数论]

  题目传送门

数学作业

题目描述

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

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

输入输出格式

输入格式:

 

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

 

输出格式:

 

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

 

输入输出样例

输入样例#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:

 1 //It is made by HolseLee on 30th May 2018
 2 //Luogu.org P3216
 3 #include<bits/stdc++.h>
 4 using namespace std;
 5 typedef long long ll;
 6 ll n,mod;
 7 struct Matrix{
 8     ll a[5][5];
 9     Matrix(){memset(a,0,sizeof(a));}
10     Matrix(ll b[5][5]){memcpy(a,b,sizeof(a));}
11     friend Matrix operator * (const Matrix a,const Matrix b){
12         Matrix ret;
13         for(int i=0;i<=2;i++)
14         for(int j=0;j<=2;j++)
15         for(int k=0;k<=2;k++)
16         ret.a[i][j]=(ret.a[i][j]+(a.a[i][k]*b.a[k][j])%mod)%mod;
17         return ret;
18     }
19 }K,T;
20 int main()
21 {
22     cin>>n>>mod;ll now=0;
23     K.a[0][0]=0;K.a[0][1]=1;K.a[0][2]=1;
24     for(ll i=10;now<n;i*=10){
25         T.a[0][0]=i%mod;T.a[0][1]=0;T.a[0][2]=0;
26         T.a[1][0]=1;T.a[1][1]=1;T.a[1][2]=0;
27         T.a[2][0]=0;T.a[2][1]=1;T.a[2][2]=1;
28         ll ka=min(i-1,n)-now;
29         while(ka){
30             if(ka&1)K=K*T;
31             T=T*T;ka>>=1;}
32         now=min(i-1,n);}
33     cout<<K.a[0][0];return 0;
34 }

猜你喜欢

转载自www.cnblogs.com/cytus/p/9113776.html