题目描述
小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题:
给定正整数 NN 和 MM ,要求计算 Concatenate (1 … N) Concatenate(1…N) ModMod MM 的值,其中 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≤10000001≤N≤1000000 ;100%的数据满足1≤N≤10^{18}1≤N≤10
18
且1≤M≤10^91≤M≤10
9
.
输出格式
输出文件 output.txt 仅包含一个非负整数,表示 Concatenate (1 … N)Concatenate(1…N) ModMod MM 的值。
输入输出样例
输入 #1
13 13
输出 #1
4
.
.
.
.
.
.
分析
.
.
.
.
.
程序:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long mo,ans[3][3],a[3][3];
void jzcf(long long x[3][3],long long y[3][3])
{
long long t[3][3];
memset(t,0,sizeof(t));
for (int i=0;i<=2;i++)
for (int j=0;j<=2;j++)
for (int k=0;k<=2;k++)
t[i][j]=(((long long)(x[i][k]%mo)*(y[k][j]%mo)+mo)%mo+t[i][j]+mo)%mo;
for (int i=0;i<=2;i++)
for (int j=0;j<=2;j++)
x[i][j]=t[i][j];
}
int main()
{
long long n,t=10;
scanf("%lld%lld",&n,&mo);
ans[0][0]=ans[1][1]=ans[2][2]=1;
while (n>=t)
{
memset(a,0,sizeof(a));
a[0][0]=t;
a[1][0]=a[2][0]=a[1][1]=a[2][1]=a[2][2]=1;
long long y=(t-1)-t/10+1;
while (y!=0)
{
if (y&1) jzcf(ans,a);
jzcf(a,a);
y>>=1;
}
t=(long long)t*10;
}
memset(a,0,sizeof(a));
a[0][0]=t;
a[1][0]=a[2][0]=a[1][1]=a[2][1]=a[2][2]=1;
long long y=n-t/10+1;
while (y!=0)
{
if (y&1) jzcf(ans,a);
jzcf(a,a);
y>>=1;
}
printf("%lld",(ans[2][0]+mo)%mo);
return 0;
}