题意
题解
先处理右侧的和式,依据个人习惯,将 i i i 用 x x x 表示 。设 m = ⌊ log x n ⌋ m=\lfloor \log_{x}^{n}\rfloor m=⌊logxn⌋,则有
∑ j = 1 n ⌈ log x j ⌉ = ∑ j = 1 n k [ k = ⌈ log x j ⌉ ] [ log x j ≤ k < log x j + 1 ] = ∑ j , k k [ 1 ≤ k ≤ m ] [ x k − 1 < j ≤ x k ] + ∑ j ( m + 1 ) [ x m < j ≤ n ] = ∑ k = 1 m k ( x k − x k − 1 ) + ( m + 1 ) ( n − x m ) = 1 x − 1 [ 1 − ( m + 1 ) x m + m x m + 1 ] + ( m + 1 ) ( n − x m ) \begin{aligned} \sum\limits_{j=1}^{n}\lceil \log_{x}^{j}\rceil &=\sum\limits_{j=1}^{n}k[k=\lceil \log_{x}^{j}\rceil][\log_{x}^{j}\leq k<\log_{x}^{j}+1] \\ &=\sum\limits_{j,k}k[1\leq k\leq m][x^{k-1}<j\leq x^k]+\sum\limits_{j}(m+1)[x^m<j\leq n] \\ &=\sum\limits_{k=1}^{m}k(x^k-x^{k-1})+(m+1)(n-x^m) \\ &=\frac{1}{x-1}[1-(m+1)x^m+mx^{m+1}]+(m+1)(n-x^m) \end{aligned} j=1∑n⌈logxj⌉=j=1∑nk[k=⌈logxj⌉][logxj≤k<logxj+1]=j,k∑k[1≤k≤m][xk−1<j≤xk]+j∑(m+1)[xm<j≤n]=k=1∑mk(xk−xk−1)+(m+1)(n−xm)=x−11[1−(m+1)xm+mxm+1]+(m+1)(n−xm)
那么有
∑ x = l r ( x − 1 ) ∑ j = 1 n ⌈ log x j ⌉ = ∑ x = l r [ 1 + n ( x − 1 ) + m n ( x − 1 ) − x m + 1 ] \sum\limits_{x=l}^{r}(x-1)\sum\limits_{j=1}^{n}\lceil \log_{x}^{j}\rceil =\sum\limits_{x=l}^{r}[1+n(x-1)+mn(x-1)-x^{m+1}] x=l∑r(x−1)j=1∑n⌈logxj⌉=x=l∑r[1+n(x−1)+mn(x−1)−xm+1] m m m 的取值只有 log n \log n logn 种,可以对满足 m m m 相同的区间 ( n m + 1 , n m ] (\sqrt[m+1]n,\sqrt[m]{n}] (m+1n,mn] 依次求解。这样的区间为 ( n , + ∞ ] , ( n , n ] , ( n 3 , n ] , ⋯ (n,+\infty],(\sqrt{n},n],(\sqrt[3]{n},\sqrt{n}],\cdots (n,+∞],(n,n],(3n,n],⋯,取与 ( l , r ] (l,r] (l,r] 的交集进行统计。对于满足 x ≤ n m x\leq \sqrt[m]n x≤mn 的最大 x x x,可以二分求解;依据 ⌊ ⌊ n / x ⌋ / x ⌋ = ⌊ n / x 2 ⌋ , x > 0 , x ∈ Z \lfloor \lfloor n/x\rfloor/x\rfloor=\lfloor n/x^2\rfloor,x>0,x\in\Z ⌊⌊n/x⌋/x⌋=⌊n/x2⌋,x>0,x∈Z 的原理进行检验,基于与快速幂类似的倍增思想可以做到 O ( log log N ) O(\log\log N) O(loglogN)。当 m ≥ 5 m\geq 5 m≥5,有 n < 2 60 → n m < 2 12 n<2^{60}\rightarrow \sqrt[m]{n}<2^{12} n<260→mn<212,对这样值域较小的情况,可以暴力求前缀和; m < 5 m<5 m<5 的情况,应用闭合表达式。
总时间复杂度 O ( N log 2 N log log N ) O(N\log^2N\log\log N) O(Nlog2NloglogN)。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l, _ = r; i < _; ++i)
typedef long long ll;
const int maxlg = 1 << 6, maxn = 1 << 12;
const ll mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;
const ll coef[6][7] = {
{
0, 1, 0, 0, 0, 0, 0},
{
0, 1, 1, 0, 0, 0, 0},
{
0, 1, 3, 2, 0, 0, 0},
{
0, 0, 1, 2, 1, 0, 0},
{
0, -1, 0, 10, 15, 6, 0},
{
0, 0, -1, 0, 5, 6, 2}};
const ll coef2[6] = {
1, 2, 6, 4, 30, 12};
int T;
ll inv[50], sum[maxlg][maxn];
ll pow_mod(ll x, ll n)
{
ll res = 1 % mod;
x %= mod;
while (n)
{
if (n & 1)
res = res * x % mod;
x = x * x % mod, n >>= 1;
}
return res;
}
ll F(int e, ll n)
{
ll x = 1, res = 0;
n %= mod;
rep(i, 0, 7) res = (res + x * coef[e][i] % mod) % mod, x = x * n % mod;
return res * inv[coef2[e]] % mod;
}
bool judge(ll x, int m, ll n)
{
ll res = n;
while (m)
{
if (m & 1)
if ((res /= x) < 1)
return 0;
m >>= 1;
if (x > (n / x) && m)
return 0;
x = x * x;
}
return 1;
}
ll find(int m, ll n, ll lim)
{
ll lb = 0, ub = lim + 1;
while (ub - lb > 1)
{
ll mid = (lb + ub) >> 1;
if (judge(mid, m, n))
lb = mid;
else
ub = mid;
}
return lb;
}
ll solve(ll l, ll r, ll n)
{
--l;
ll res = (r - l) % mod;
res = (res + (n % mod) * (F(1, r - 1) - F(1, l - 1)) % mod) % mod;
ll lb, ub = inf;
rep(m, 0, maxlg)
{
if (ub < l)
break;
lb = find(m + 1, n, ub);
if (!(r <= lb || ub <= l))
{
ll a = max(lb, l), b = min(ub, r);
ll d = (F(1, b - 1) - F(1, a - 1)) * m % mod, d2;
d = (n % mod) * d % mod;
res = (res + d) % mod;
if (m + 1 <= 5)
d2 = (F(m + 1, b) - F(m + 1, a)) % mod;
else
d2 = (sum[m + 1][b] - sum[m + 1][a]) % mod;
res = (res - d2) % mod;
}
ub = lb;
}
return (res + mod) % mod;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
rep(j, 1, maxn)
{
ll x = 1;
rep(i, 0, maxlg) sum[i][j] = (sum[i][j] + x) % mod, x = x * j % mod;
}
rep(i, 0, maxlg) rep(j, 1, maxn) sum[i][j] += sum[i][j - 1];
rep(i, 1, 50) inv[i] = pow_mod(i, mod - 2);
cin >> T;
while (T--)
{
ll l, r, n;
cin >> l >> r >> n;
cout << solve(l, r, n) << '\n';
}
}