Description
小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题:给定正整数 N 和 M
要求计算 Concatenate (1 … N) Mod M 的值,其中 Concatenate (1 …N)是将所有正整数 1, 2, …, N 顺序连接起来得到的数。
例如,N = 13, Concatenate (1 … N)=12345678910111213.小C 想了大半天终于意识到这是一道不可能手算出来的题目,
于是他只好向你求助,希望你能编写一个程序帮他解决这个问题。
Input
只有一行且为用空格隔开的两个正整数N和M,
1
≤
N
≤
1
0
18
1≤N≤10^{18}
1≤N≤1018且
1
≤
M
≤
1
0
9
1≤M≤10^9
1≤M≤109.
Output
仅包含一个非负整数,表示 Concatenate (1 … N) Mod M 的值。
Sample Input
13 13
Sample Output
4
分析:
设
f
[
i
]
=
C
o
n
c
a
t
e
n
a
t
e
(
1..
i
)
f[i]=Concatenate(1..i)
f[i]=Concatenate(1..i)
则
f
[
i
]
=
f
[
i
−
1
]
∗
1
0
l
e
n
+
i
f[i]=f[i-1]*10^{len}+i
f[i]=f[i−1]∗10len+i,其中
l
e
n
len
len为
i
i
i的位数。
考虑矩阵递推。首先至少有
f
[
i
−
1
]
f[i-1]
f[i−1]和
i
i
i这两个项,然后发现不能实现对
i
i
i的递推,还要加一个常数项。
所以,
(
f
[
i
−
1
]
i
1
)
∗
(
1
0
l
e
n
0
0
1
1
0
0
1
1
)
=
(
f
[
i
]
i
+
1
1
)
\begin{pmatrix} f[i-1] & i & 1 \end{pmatrix}*\begin{pmatrix}10^{len} & 0 & 0 \\ 1 & 1 & 0 \\ 0 & 1 &1 \end{pmatrix}=\begin{pmatrix} f[i] & i+1 & 1 \end{pmatrix}
(f[i−1]i1)∗⎝⎛10len10011001⎠⎞=(f[i]i+11)
因为不同位数的数矩阵不同,所以要分段计算。
代码:
/**************************************************************
Problem: 2326
User: ypxrain
Language: C++
Result: Accepted
Time:52 ms
Memory:1292 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
using namespace std;
LL n,m,k,num,x,last;
struct matrix{
int n,m;
LL a[4][4];
}A,B,C;
matrix operator *(matrix a,matrix b)
{
matrix c;
c.n=a.n,c.m=b.m;
for (int i=0;i<=c.n;i++)
{
for (int j=0;j<=c.m;j++) c.a[i][j]=0;
}
for (int k=1;k<=a.m;k++)
{
for (int i=1;i<=a.n;i++)
{
for (int j=1;j<=b.m;j++)
{
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%m)%m;
}
}
}
return c;
}
void power(LL k)
{
if (k==1)
{
B=A;
return;
}
power(k/2);
B=B*B;
if (k&1) B=B*A;
}
int main()
{
scanf("%lld%lld",&n,&m);
C.n=1,C.m=3;
C.a[1][1]=0,C.a[1][2]=1,C.a[1][3]=1;
num=1;
x=last=0;
while (x<n)
{
x=x*10+9;
if (x>=n) k=n-last;
else k=x-last;
last=x;
num=(num*10)%m;
A.n=3,A.m=3;
A.a[1][1]=num,A.a[1][2]=0,A.a[1][3]=0;
A.a[2][1]=1,A.a[2][2]=1,A.a[2][3]=0;
A.a[3][1]=0,A.a[3][2]=1,A.a[3][3]=1;
power(k);
C=C*B;
}
printf("%lld\n",C.a[1][1]);
}