类欧几里得算法学习笔记

类欧几里得算法

类欧几里得算法可以在O(log2max{a,b})的时间内求解形如i=0nai+bc的式子,而他的求解过程酷似欧几里得算法,故而得名。

基础款

f(a,b,c,n)=i=0nai+bc

  • case 1:a=0

    f(a,b,c,n)=bc(n+1)

  • case 2:ac||bc

    f(a,b,c,n)=i=0nai+bc=i=0n(acc+a%c)i+bcc+b%cc=i=0naci+i=0nbc+i=0n(a%c)i+b%cc=acn(n+1)2+bc(n+1)+f(a%c,b%c,c,n)

  • case 3:a<c&&b<c
    先考虑一个问题:已知ai+bc=k,求i的范围,以上均为正整数。

    kai+bc<k+1kcbai<c(k+1)bkcb+a1aic(k+1)b+a1a1

    我们变换求和的方法,枚举k

    f(a,b,c,n)=i=1nai+bc=k=0an+bc1(c(k+1)b+a1a1kcb+a1a+1)k+(nan+bccb+a1a+1)an+bc=k=1an+bcckb1akk=0an+bc1ckb1akk=0an+bc1c(k+1)b1a+(nan+bccb1a)an+bc=an+bcnk=0an+bc1c(k+1)b1a=an+bcnf(c,cb1,a,an+bc1)

我们发现上面的计算过程与欧几里得算法类似,复杂度是O(log2max{a,b})

进阶款

g(a,b,c,n)=i=0nai+bc2

h(a,b,c,n)=i=0nai+bci

等会我们会看到这两个式子具有关联性。

  • case 1:a=0
    g(a,b,c,n)=bc2(n+1)h(a,b,c,n)=bcn(n+1)2

  • case 2:ac||bc

    g(a,b,c,n)=i=0nai+bc2=i=0n(acc+a%c)i+bcc+b%cc2=i=0n(aci+bc+(a%c)i+b%cc)2=ac2n(n+1)(2n+1)6+acbcn(n+1)+bc2(n+1)+g(a%c,b%c,c,n)+2ach(a%c,b%c,c,n)+2bcf(a%c,b%c,c,n)h(a,b,c,n)=i=0nai+bci=i=0n(acc+a%c)i+bcc+b%cci=acn(n+1)(2n+1)6+bcn(n+1)2+h(a%c,b%c,c,n)

  • case 3:a<c&&b<c

    g(a,b,c,n)=i=1nai+bc2=k=0an+bc1(c(k+1)b+a1a1kcb+a1a+1)k2+(nan+bccb+a1a+1)an+bc2=k=1an+bcckb1ak2k=0an+bc1ckb1ak2k=0an+bc1c(k+1)b1ak=0an+bc12kc(k+1)b1a+(nan+bccb1a)an+bc2=an+bc2nf(c,cb1,a,an+bc1)2h(c,cb1,a,an+bc1)h(a,b,c,n)=i=0nai+bci=k=0an+bc1k2(c(k+1)b1ackb1a)(c(k+1)b1a+ckb1a+1)+12na+bc(nna+bccb1a)(n+na+bccb1a+1)=12i=0na+bc1i(c(i+1)b1a2cib1a2)+12i=0na+bc1i(c(i+1)b1acib1a)12na+bc(nna+bccb1a)(n+na+bccb1a+1)=na+bcn(n+1)212g(c,cb1,a,an+bc1)12f(c,cb1,a,an+bc1)

综上,

f(a,b,c,n)={bc(n+1),a=0acn(n+1)2+bc(n+1)+f(a%c,b%c,c,n),ac||bcan+bcnf(c,cb1,a,an+bc1),a<c&&b<cg(a,b,c,n)={bc2(n+1),a=0ac2n(n+1)(2n+1)6+acbcn(n+1)+bc2(n+1)+g(a%c,b%c,c,n)+2ach(a%c,b%c,c,n)+2bcf(a%c,b%c,c,n),ac||bcan+bc2nf(c,cb1,a,an+bc1)2h(c,cb1,a,an+bc1),a<c&&b<ch(a,b,c,n)={bcn(n+1)2,a=0acn(n+1)(2n+1)6+bcn(n+1)2+h(a%c,b%c,c,n),ac||bcna+bcn(n+1)212g(c,cb1,a,an+bc1)12f(c,cb1,a,an+bc1),a<c&&b<c

code:P5170 【模板】类欧几里得算法

#include <cstdio>
#include <iostream>

using namespace std;

const int mo = 998244353;

struct Mint {
    int a;
    Mint() {}
    Mint(int o) { a = o; }
    Mint operator+(const Mint& o) const { return (a + o.a) % mo; }
    Mint operator+(const int& o) const { return (o + a) % mo; }
    Mint operator-(const Mint& o) const {
        return Mint(((a - o.a) % mo) + mo) % mo;
    }
    Mint operator*(const Mint& o) const { return Mint(1ll * a * o.a % mo); }
    Mint operator/(const Mint& o) const { return Mint(a / o.a); }
    operator int() { return a; }
};

struct func {
    Mint f, g, h;
    func() {}
    func(Mint o, Mint p, Mint q) {
        f = o;
        g = p;
        h = q;
    }
};

const Mint inv2 = Mint((mo + 1) >> 1);
const Mint inv3 = Mint((mo + 1) / 3);
const Mint inv6 = Mint(inv2 * inv3);

func calc(int A, int B, int C, int N) {
    Mint a = A;
    Mint b = B;
    Mint c = C;
    Mint n = N;
    if (!A) {
        return func((b / c) * (n + 1), (b / c) * (b / c) * (n + 1),
                    (b / c) * n * (n + 1) * inv2);
    }
    func ans;
    if (A >= C || B >= C) {
        ans = calc(A % C, B % C, C, N);
        return func((a / c) * n * (n + 1) * inv2 + (b / c) * (n + 1) + ans.f,
                    n * (n + 1) * (n + n + 1) * inv6 * (a / c) * (a / c) +
                        (a / c) * (b / c) * n * (n + 1) +
                        (b / c) * (b / c) * (n + 1) + ans.g +
                        (a / c) * ans.h * Mint(2) + (b / c) * ans.f * Mint(2),
                    (a / c) * n * (n + 1) * (n + n + 1) * inv6 +
                        (b / c) * n * (n + 1) * inv2 + ans.h);
    }
    int m = (1ll * A * N + B) / C;
    Mint M = Mint(m);
    ans = calc(C, C - B - 1, A, m - 1);
    return func(M * n - ans.f, n * M * M - ans.h * Mint(2) - ans.f,
                M * n * n * inv2 + M * n * inv2 - ans.g * inv2 - ans.f * inv2);
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        int a, b, c, n;
        scanf("%d%d%d%d", &n, &a, &b, &c);
        func ans = calc(a, b, c, n);
        printf("%d %d %d\n", ans.f, ans.g, ans.h);
    }
    return 0;
}
posted @   clapp  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示