题目:BZOJ2326.
题目大意:给定一个数
n
n
n,求由
1
1
1~
n
n
n按顺序写出来合并得到的数模
M
M
M的值.例如
n
n
n为
13
13
13,那么写出来的数为
12345678910111213
12345678910111213
12345678910111213.
1
≤
n
≤
1
0
18
,
1
≤
m
≤
1
0
9
1\leq n\leq 10^{18},1\leq m\leq 10^9
1≤n≤1018,1≤m≤109.
乍一看感觉还挺难的,但是思考一下会发现其实只要边加数边模就可以了,只是数的位数不同会比较难处理,分段一下就好,不过直接暴力加数会TLE.
然后仔细思考一下,设
f
[
i
]
f[i]
f[i]表示加到数
i
i
i的时候的值且
1
0
k
≤
i
<
1
0
k
+
1
10^k\leq i< 10^{k+1}
10k≤i<10k+1,那么显然
f
[
i
]
=
f
[
i
−
1
]
∗
1
0
k
+
1
+
i
f[i]=f[i-1]*10^{k+1}+i
f[i]=f[i−1]∗10k+1+i.把这个转移用矩阵写出来:
[
?
?
?
?
?
?
?
?
?
]
[
f
[
i
]
i
1
]
=
[
f
[
i
]
∗
1
0
k
+
i
+
1
i
+
1
1
]
\left[\begin{array}{ccc} ?&?&? \\?&?&? \\?&?&? \end{array}\right] \left[\begin{array}{c} f[i]\\ i\\ 1\\ \end{array}\right]= \left[\begin{array}{c} f[i]*10^k+i+1\\ i+1\\ 1\\ \end{array}\right]
⎣⎡?????????⎦⎤⎣⎡f[i]i1⎦⎤=⎣⎡f[i]∗10k+i+1i+11⎦⎤
很容易把左边的这个矩阵填出来:
[
1
0
k
1
1
0
1
1
0
0
1
]
\left[\begin{array}{ccc} 10^k&1&1\\ 0&1&1\\ 0&0&1 \end{array}\right]
⎣⎡10k00110111⎦⎤
然后分段写矩阵乘法就可以了,不过注意要写快(gui)速乘,时间复杂度 O ( log n ) O(\log n) O(logn),代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=3;
LL n,mod;
LL mul(LL a,LL b){
LL s=0;
for (;b;b>>=1,a=a+a%mod)
if (b&1) s=s+a%mod;
return s;
}
struct matrix{
int n,m;
LL v[N+9][N+9];
matrix operator * (const matrix &p)const{
matrix tmp=matrix();
tmp.n=n;tmp.m=p.m;
for (int i=1;i<=tmp.n;++i)
for (int k=1;k<=m;++k)
for (int j=1;j<=tmp.m;++j)
tmp.v[i][j]=(tmp.v[i][j]+mul(v[i][k],p.v[k][j]))%mod;
return tmp;
}
}ans,f;
matrix e(int k){
matrix e=matrix();
e.n=e.m=k;
for (int i=1;i<=e.n;++i)
for (int j=1;j<=e.m;++j)
e.v[i][j]=i==j?1:0;
return e;
}
matrix go(LL k){
matrix f=matrix();
f.n=f.m=3;
f.v[1][1]=k;
f.v[1][2]=f.v[1][3]=f.v[2][2]=f.v[2][3]=f.v[3][3]=1;
return f;
}
matrix power(matrix a,LL k){
matrix s=e(a.n);
for (;k;k>>=1,a=a*a)
if (k&1) s=s*a;
return s;
}
Abigail into(){
scanf("%lld%lld",&n,&mod);
}
Abigail work(){
ans.n=3;ans.m=1;
ans.v[1][1]=0;ans.v[2][1]=0;ans.v[3][1]=1;
LL g;
for (g=1;g*10<=n;g*=10)
ans=power(go(g*10),g*9)*ans;
ans=power(go(g*10),n-g+1)*ans;
}
Abigail outo(){
printf("%lld\n",ans.v[1][1]);
}
int main(){
into();
work();
outo();
return 0;
}