链接:
题目大意:
求:
[ ext{Concatenate}(n) mod m
]
其中 ( ext{Concatenate}(n)) 表示将 (1 sim n) 所有正整数顺序连接在一起得到的数。
正文:
可以把题目转化为递推的形式:
[egin{aligned}f(1)&=1\
f(n)&=left(10^{leftlfloorlog_{10} n
ight
floor+1}f(n-1)+n
ight)mod mend{aligned}]
时间复杂度 (mathcal{O}(n)) 不能接受,考虑用矩阵优化:
[egin{bmatrix}f(n)\n\1end{bmatrix}=egin{bmatrix}10^{leftlfloorlog_{10} n
ight
floor+1}&1&1\0&1&1\0&0&1end{bmatrix}cdotegin{bmatrix}f(n-1)\n-1\1end{bmatrix}
]
因为 (leftlfloorlog_{10} n ight floor+1) 随时可能变化,就对于每个单独处理,因为 (nleq10^{18}),所以最多循环 (18) 次。
总时间复杂度 (mathcal{O}(log n))。
代码:
const int N = 110;
int f[N];
ll n, mod;
struct matrix
{
ll mat[N][N];
int n, m;
matrix(int _n, int _m)
{
n = _n, m = _m;
memset(mat, 0, sizeof mat);
}
inline ll* operator [] (int b) { return mat[b];}
}F(3, 1);
inline matrix operator*(matrix a, matrix b)
{
matrix c(a.n, b.m);
for (int i = 1; i <= a.n; i++)
for (int j = 1; j <= b.m; j++)
for (int k = 1; k <= a.m; k++)
c[i][j] = (c[i][j] + (a[i][k] * b[k][j]) % mod) % mod;
return c;
}
matrix qpow(matrix a, ll b)
{
matrix ans(a.n, a.m);
for (int i = 1; i <= ans.n; i++)
ans[i][i] = 1;
for (; b; b >>= 1)
{
if(b & 1) ans = ans * a;
a = a * a;
}
return ans;
}
void Solve (ll k, ll b)
{
matrix base(3, 3);
base[1][1] = k % mod,
base[1][2] = base[1][3] = base[2][2] = base[2][3] = base[3][3] = 1;
F = qpow(base, b) * F;
}
int main()
{
scanf ("%lld%lld", &n, &mod);
ll r = 10;
F[3][1] = 1;
for (; r <= n; r *= 10)
Solve (r, r - (r / 10));
Solve (r, n - (r / 10) + 1);
printf ("%lld
", F[1][1]);
return 0;
}