考虑求
Concatenate(L...R)
的值,其中
[L,R]
之间的数都是
x
位数。
可以得到,
则有:
f[L]=L
f[i]=f[i−1]∗10x+i
建立一个
3∗3
的转移矩阵
P
,第一行代表
⎡⎣⎢10x00110111⎤⎦⎥
3∗1 的边界矩阵 F :
此时可以得出, f[R]=(PR−L∗F)[1][1] 。
用这样的方法,就可以求出 Concatenate(1...9) , Concatenate(10...99) , Concatenate(100...999) ,…, Concatenate(10k,N) 的值,然后乱搞即可。
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll nn, E10[1005]; int CYX, Exp[1005], np[25];
struct cyx {
int m, n, a[15][15];
cyx() {}
cyx(int _m, int _n) :
m(_m), n(_n) {memset(a, 0, sizeof(a));}
friend inline cyx operator * (cyx x, cyx y) {
cyx z = cyx(x.m, y.n); int i, j, k;
for (i = 1; i <= z.m; i++) for (j = 1; j <= z.n; j++)
for (k = 1; k <= x.n; k++)
(z.a[i][j] += 1ll * x.a[i][k] * y.a[k][j] % CYX)
%= CYX;
return z;
}
friend inline cyx operator ^ (cyx x, ll y) {
cyx aa = x, z = cyx(x.m, x.n); int i;
for (i = 1; i <= z.m; i++) z.a[i][i] = 1;
while (y) {
if (y & 1) z = z * aa;
aa = aa * aa;
y >>= 1;
}
return z;
}
} F, P;
int qpow(int a, ll b) {
int res = 1;
while (b) {
if (b & 1) res = 1ll * res * a % CYX;
a = 1ll * a * a % CYX;
b >>= 1;
}
return res;
}
int solve(int w, ll mx) {
F.a[1][1] = F.a[2][1] = Exp[w - 1];
F.a[3][1] = 1; P.a[1][1] = Exp[w];
F = (P ^ mx - E10[w - 1]) * F;
return F.a[1][1];
}
inline int read() {
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
int main() {
int i, cnt = 0, res = 0;
cin >> nn; CYX = read(); Exp[0] = E10[0] = 1;
for (i = 1; i <= 1000; i++)
Exp[i] = 1ll * Exp[i - 1] * 10 % CYX;
for (i = 1; i <= 18; i++) E10[i] = E10[i - 1] * 10;
F = cyx(3, 1); P = cyx(3, 3);
P.a[1][2] = P.a[1][3] = P.a[2][2]
= P.a[2][3] = P.a[3][3] = 1; ll bb = nn;
while (bb) cnt++, bb /= 10;
for (i = 1; i <= cnt; i++) {
ll mx = i == cnt ? nn : E10[i] - 1;
res = 1ll * res *
qpow(qpow(10, mx - E10[i - 1] + 1), i) % CYX;
(res += solve(i, mx)) %= CYX;
}
printf("%d\n", res);
return 0;
}