Solution -「Luogu 5170」类欧几里得算法

推柿子大赛了属于是。

题目要求三个柿子,不妨分别记为:

\[\begin {align} f (a, b, c, n) &= \sum \limits _{i = 0} ^{n} \lfloor \frac {ai + b} {c} \rfloor \nonumber \\ g (a, b, c, n) &= \sum \limits _{i = 0} ^{n} \lfloor \frac {ai + b} {c} \rfloor ^2 \nonumber \\ h (a, b, c, n) &= \sum \limits _{i = 0} ^{n} i\lfloor \frac {ai + b} {c} \rfloor \nonumber \end {align} \]

分开化简即可。


Case #1 F.

分类讨论:

  • \(a = 0\),则 \(f (a, b, c, n) = (n + 1) \lfloor \frac {b} {c} \rfloor\)

  • \(a \geq c\)\(b \geq c\),则:

    \[\begin {align} f (a, b, c, n) &= \sum \limits _{i = 0} ^{n} (\lfloor \frac {i(a \bmod c) + (b \bmod c)} {c} \rfloor + i \lfloor \frac {a} {c} \rfloor + \lfloor \frac {b} {c} \rfloor) \nonumber \\ &= f (a \bmod c, b \bmod c, c, n) + \frac {n (n + 1)} {2} \lfloor \frac {a} {c} \rfloor + (n + 1) \lfloor \frac {b} {c} \rfloor \nonumber \end {align} \]

  • \(a < c\)\(b < c\),记 \(m = \lfloor \frac {an + b} {c} \rfloor\),则有:

    \[\begin {align} f (a, b, c, n) &= \sum \limits _{i = 0} ^{n} \sum \limits _{j = 1} ^{m} [j \leq \lfloor \frac {ai + b} {c} \rfloor] \nonumber \\ &= \sum \limits _{i = 0} ^{n} \sum \limits _{j = 0} ^{m - 1} [j c + c < ai + b + 1] \nonumber \\ &= \sum \limits _{j = 0} ^{m - 1} \sum \limits _{i = 0} ^{n} [i > \lfloor \frac {jc + c - b - 1} {a} \rfloor] \nonumber \\ &= \sum \limits _{j = 0} ^{m - 1} (n - \lfloor \frac {jc + c - b - 1} {a} \rfloor) \nonumber \\ &= nm - f(c, c - b - 1, a, m - 1) \nonumber \end {align} \]

接下来递归求解。不难发现,递归出口为 \(a = 0\)

在其他递归过程中,若只关注 \(a\)\(c\) 两项,可以发现我们是在交错执行以下两步:交换 $a $ 和 \(c\)、将 \(a\)\(c\) 取模。这与欧几里得算法类似,故具有和欧几里得算法一样的 \(O(\log )\) 时间复杂度。


Case #2 G & H.

把它们放在一起是因为求法互相依赖,巨大多公式警告

继续分类讨论。

  • \(a = 0\),则:

    \[\begin {align} g (a, b, c, n) &= (n + 1) \lfloor \frac {b} {c} \rfloor ^ 2 \nonumber \\ h(a, b, c, n) &= \frac {n(n + 1)} {2} \lfloor \frac {b} {c} \rfloor \nonumber \end {align} \]

  • \(a \geq c\)\(b \geq c\),则:

    \[\begin {align} g (a, b, c, n) &= \sum \limits _{i = 0} ^{n} (\lfloor \frac {i (a \bmod c) + (b \bmod c)} {c} \rfloor + i \lfloor \frac {a} {c} \rfloor + \lfloor \frac {b} {c} \rfloor) ^2 \nonumber \\ &= \sum \limits _{i = 0} ^{n} \lfloor \frac {i (a \bmod c) + (b \bmod c)} {c} \rfloor) ^2 + 2 (i\lfloor \frac {a} {c} \rfloor + \lfloor \frac {b} {c} \rfloor)\lfloor \frac {i (a \bmod c) + (b \bmod c)} {c} \rfloor + (i\lfloor \frac {a} {c} \rfloor + \lfloor \frac {b} {c} \rfloor)^2 \nonumber \\ &= g(a \bmod c, b \bmod c, c, n) + 2 \lfloor \frac {a} {c} \rfloor h (a\bmod c, b \bmod c, c, n) + 2 \lfloor \frac {b} {c} \rfloor f (a\bmod c, b \bmod c, c, n) \nonumber \\ &+ \sum \limits _{i = 0} ^{n} (\lfloor \frac {a} {c} \rfloor ^2 i^2 + 2 \lfloor \frac {a} {c} \rfloor \lfloor \frac {b} {c} \rfloor i + \lfloor \frac {b} {c} \rfloor ^2) \nonumber \\ &= g(a \bmod c, b \bmod c, c, n) + 2 \lfloor \frac {a} {c} \rfloor h (a\bmod c, b \bmod c, c, n) + 2 \lfloor \frac {b} {c} \rfloor f (a\bmod c, b \bmod c, c, n) \nonumber \\ &+ \frac {n (n + 1) (2n + 1)} {6} \lfloor \frac {a} {c} \rfloor ^2 + n(n + 1) \lfloor \frac {a} {c} \rfloor \lfloor \frac {b} {c} \rfloor + (n + 1)\lfloor \frac {b} {c} \rfloor ^2 \nonumber \end {align} \]

    接下来关注到 \(h (a, b, c, n)\)

    \[\begin {align} h (a, b, c, n) &= \sum \limits _{i = 0} ^{n} [i \lfloor \frac {i (a \bmod c) + (b \bmod c)} {c} \rfloor + i (i \lfloor \frac {a} {c} \rfloor + \lfloor \frac {b} {c} \rfloor)] \nonumber \\ &= h (a \bmod c, b \bmod c, c, n) + \sum \limits _{i = 0} ^{n} (i^2 \lfloor \frac {a} {c} \rfloor + i \lfloor {b} {c} \rfloor) \nonumber \\ &= h (a \bmod c, b \bmod c, c, n) + \frac {n(n + 1)(2n + 1)} {6} \lfloor \frac {a} {c} \rfloor + \frac {n (n + 1)} {2} \lfloor \frac {b} {c} \rfloor \nonumber \end {align} \]

  • \(a < c\)\(b < c\),仍记 \(m = \lfloor \frac {an + b} {c} \rfloor\),则有:

    \[\begin {align} g (a, b, c, n) &= 2 \sum \limits _{i = 0} ^{n} \frac {\lfloor \frac {ai + b} {c} \rfloor (\lfloor \frac {ai + b} {c} \rfloor + 1)} {2} - \sum \limits _{i = 0} ^{n} \lfloor \frac {ai + b} {c} \rfloor \nonumber \\ &= -f (a, b, c, n) + 2 \sum \limits _{i = 0} ^{n} \sum \limits _{j = 1} ^{m} j [j \leq \lfloor \frac {ai + b} {c} \rfloor] \nonumber \\ &= -f(a, b, c, n) + 2 \sum \limits _{i = 0} ^{n} \sum \limits _{j = 0} ^{m - 1} (j + 1) [jc + c \leq ai + b + 1] \nonumber \\ &= -f(a, b, c, n) + 2\sum \limits _{j = 0} ^{m - 1} (j + 1) \sum \limits _{i = 0} ^{n} [i > \lfloor \frac {jc + c - b - 1} {a} \rfloor] \nonumber \\ &= -f(a, b, c, n) + 2\sum \limits _{j = 0} ^{m - 1} (j + 1) (n - \lfloor \frac {jc + c - b - 1} {a} \rfloor) \nonumber \\ &= nm(m + 1) - f(a, b, c, n) - 2 (\sum \limits _{j = 0} ^{m - 1} j \lfloor \frac {jc + c - b - 1} {a} \rfloor + \sum \limits _{j = 0} ^{m - 1} \lfloor \frac {jc + c - b - 1} {a} \rfloor) \nonumber \\ &= nm^2 + nm - f (a, b, c, n) - 2h(c, c - b - 1, a, m - 1) - 2f(c, c - b - 1, a, m - 1) \nonumber \end {align} \]

    不要慌还有 \(h(a, b, c, n)\)

    \[\begin {align} h (a, b, c, n) &= \sum \limits _{i = 0} ^{n} i \sum \limits _{j = 1} ^{m} [j \leq \lfloor \frac {ai + b} {c} \rfloor] \nonumber \\ &= \sum \limits _{i = 0} ^{n} i \sum \limits _{j = 0} ^{m - 1} [jc + c < ai + b + 1] \nonumber \\ &= \sum \limits _{j = 0} ^{m - 1} \sum \limits _{i = 0} ^{n} i [i > \lfloor \frac {jc + c - b - 1} {a} \rfloor] \nonumber \\ &= \frac {mn(n + 1)} {2} - \sum \limits _{j = 0} ^{m - 1} \sum \limits _{i = 0} ^{n} i[i \leq \lfloor \frac {jc + c - b - 1} {a} \rfloor] \nonumber \\ &= \frac {mn(n + 1)} {2} - \sum \limits _{j = 0} ^{m - 1} \sum \limits _{i = 0} ^{\lfloor \frac {jc + c - b - 1} {a} \rfloor} i \nonumber \\ &= \frac {mn(n + 1)} {2} - \sum \limits _{j = 0} ^{m - 1} \frac {\lfloor \frac {jc + c - b - 1} {a} \rfloor (\lfloor \frac {jc + c - b - 1} {a} \rfloor + 1)} {2} \nonumber \\ &= \frac {1} {2} [mn(n + 1) - \sum \limits _{j = 0} ^{m - 1} \lfloor \frac {jc + c - b - 1} {a} \rfloor^2 - \sum \limits _{j = 0} ^{m - 1} \lfloor \frac {jc + c - b - 1} {a} \rfloor] \nonumber \\ &= \frac {1} {2} [mn(n + 1) - g(c, c - b - 1, a, m - 1) - f (c, c - b - 1, a, m - 1)] \nonumber \end {align} \]


Case #3 All.

呜呜呜到这里柿子终于推完了。

显然这三个函数的柿子结构是类似的,我们考虑递归同时求解三个函数即可。

#include <cstdio>

typedef long long LL;
int Abs (int x) { return x < 0 ? -x : x; }
int Max (int x, int y) { return x > y ? x : y; }
int Min (int x, int y) { return x < y ? x : y; }

int Read () {
    int x = 0, k = 1;
    char s = getchar ();
    while (s < '0' || s > '9') {
        if (s == '-')
            k = -1;
        s = getchar ();
    }
    while ('0' <= s && s <= '9') 
        x = (x << 3) + (x << 1) + (s ^ 48), s = getchar ();
    return x * k;
}

void Write (LL x) {
    if (x < 0)
        putchar ('-'), x = -x;
    if (x > 9)
        Write (x / 10);
    putchar (x % 10 + '0');
}

void Print (LL x, char s) { Write (x), putchar (s); }

const int Mod = 998244353;
const LL Inv6 = 166374059;
const LL Inv2 = 499122177;

struct Node {
    LL f, g, h;
    Node () {}
    Node (LL F, LL G, LL H) { f = F, g = G, h = H; }
};

LL Sum (LL n) { return n * (n + 1) % Mod * Inv2 % Mod; }
LL Squa (LL n) { return n * (n + 1) % Mod * (2 * n % Mod + 1) % Mod * Inv6 % Mod; }

Node Calc (LL a, LL b, LL c, LL n) {
    Node Res;
    if (!a) {
        Res.f = (n + 1) * (b / c) % Mod;
        Res.g = (b / c) * (b / c) % Mod * (n + 1) % Mod;
        Res.h = Sum (n) * (b / c) % Mod;
    }
    else if (a >= c || b >= c) {
        Node Tmp = Calc (a % c, b % c, c, n);
        Res.f = (Tmp.f + Sum (n) * (a / c) % Mod + (n + 1) * (b / c) % Mod) % Mod;
        Res.g = (Tmp.g + 2 * (a / c) % Mod * Tmp.h % Mod + 2 * (b / c) % Mod * Tmp.f) % Mod;
        Res.g = (Res.g + Squa (n) *  (a / c) % Mod * (a / c) % Mod) % Mod;
        Res.g = (Res.g + n * (n + 1) % Mod * (a / c) % Mod * (b / c) % Mod) % Mod;
        Res.g = (Res.g + (n + 1) * (b / c) % Mod * (b / c) % Mod) % Mod;
        Res.h = (Tmp.h + Squa (n) * (a / c) % Mod + Sum (n) * (b / c) % Mod) % Mod;
    }
    else {
        LL m = (a * n + b) / c;
        Node Tmp = Calc (c, c - b - 1, a, m - 1);
        Res.f = (n * m % Mod - Tmp.f) % Mod;
        Res.f = (Res.f + Mod) % Mod;
        Res.g = (n * m % Mod * m % Mod + n * m % Mod - Res.f - 2 * Tmp.h % Mod - 2 * Tmp.f % Mod) % Mod;
        Res.g = (Res.g + Mod) % Mod;
        Res.h = (m * n % Mod * (n + 1) % Mod - Tmp.g - Tmp.f) % Mod;
        Res.h = (Res.h + Mod) % Mod * Inv2 % Mod;
    }
    return Res;
}

int main () {
    int t = Read ();
    while (t--) {
        LL n = Read (), a = Read (), b = Read (), c = Read ();
        Node Res = Calc (a, b, c, n);
        Print (Res.f, ' '), Print (Res.g, ' '), Print (Res.h, '\n');
    }
    return 0;
}
posted @ 2022-07-13 10:09  STrAduts  阅读(39)  评论(0)    收藏  举报