P6826「EZEC-4」顶的和式

题意

传送门 P6826「EZEC-4」月下轻花舞

题解

先处理右侧的和式,依据个人习惯,将 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=1nlogxj=j=1nk[k=logxj][logxjk<logxj+1]=j,kk[1km][xk1<jxk]+j(m+1)[xm<jn]=k=1mk(xkxk1)+(m+1)(nxm)=x11[1(m+1)xm+mxm+1]+(m+1)(nxm)
那么有
∑ 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=lr(x1)j=1nlogxj=x=lr[1+n(x1)+mn(x1)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 xmn 的最大 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,xZ 的原理进行检验,基于与快速幂类似的倍增思想可以做到 O ( log ⁡ log ⁡ N ) O(\log\log N) O(loglogN)。当 m ≥ 5 m\geq 5 m5,有 n < 2 60 → n m < 2 12 n<2^{60}\rightarrow \sqrt[m]{n}<2^{12} n<260mn <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';
    }
}

猜你喜欢

转载自blog.csdn.net/neweryyy/article/details/120190933