Loading

模版类欧几里得

模版类欧几里得

这个东西,说他没用,确实极少会见到。去推这个柿子也完全是因为兴趣(顺便练习一下推柿子的能力),整体来说,这个推柿子难度不高,基本上有小学知识就能够理解。

这里知有代数解法,几何意义本人太菜了还不会。

Base 题目

给定 $n,\,a,\,b,\,c$ ,分别求 $\sum\limits_{i=0}^{n}\lfloor \dfrac{ai+b}{c} \rfloor\,,\ \sum\limits_{i=0}^{n}{\lfloor \dfrac{ai+b}{c} \rfloor}^2\,,\ \sum\limits_{i=0}^{n}i\lfloor \dfrac{ai+b}{c} \rfloor$。

Part $\mathrm{I}$ :$f$

先来讨论第一个,在这里我们设其为 $f$,更具体的,有

$$ f(a,b,c,n)=\sum_{x=0}^{n}\lfloor \frac{ax+b}{c} \rfloor $$

(这里用 $x$ 主要是笔者本人觉得 $ai$ 有时候会错看成数组下标)

主要套路有两个:取模和化贡献。

取模

取模意义在于能够把 $a,b\ge c$ 化为 $a,b < c$ 的形式。

显然有 $\alpha = \alpha \bmod \beta + (\alpha - \alpha \bmod \beta)$,直接暴力拆开来。

$$ f(a,b,c,n)=\sum_{x=0}^{n}\lfloor \dfrac{(a \bmod c)x + (a-a\bmod c)x + (b\bmod c)+(b-b\bmod c)}{c}\rfloor $$

发现第二项和第四项都是可以整除 $c$ 的,因此可以直接提出来。

$$ \begin{aligned} &=\sum_{x=0}^{n}\lfloor \dfrac{(a \bmod c)x + (b\bmod c)}{c}\rfloor + \dfrac{(a-a\bmod c)x+(b-b\bmod c)}{c}\\ &=\sum_{x=0}^{n}\lfloor \dfrac{(a \bmod c)x + (b\bmod c)}{c}\rfloor + \lfloor\dfrac{a}{c}\rfloor x+ \lfloor \dfrac{b}{c} \rfloor \end{aligned} $$

前面的东西就是 $f(a\bmod c,b\bmod c,c,n)$ 第二个可以求和提出来,最后一项直接提出来就好,因此我们有了如下式子:

$$ f(a,b,c,n)=\dfrac{n(n+1)}{2}\lfloor\dfrac{a}{c}\rfloor + (n+1)\lfloor \dfrac{b}{c} \rfloor + f(a\bmod c,b\bmod c,c,n) $$

化贡献

接下来考虑如何快速计算一个 $f$。

我们把 $\lfloor \dfrac{ax+b}{c} \rfloor$ 看成这样一个东西:$\sum\limits_{j=0}^{\lfloor \frac{ax+b}{c} \rfloor-1}$,这样做的原因主要是为了能够凑出来一种递归的形式(其实我也不太清楚,也只能这样解释了)。带入 + 交换求和顺序有:

$$ \begin{aligned} f(a,b,c,n)&=\sum_{x=0}^{n}\sum\limits_{j=0}^{\lfloor \frac{ax+b}{c} \rfloor-1}1\\ &=\sum_{j=0}^{\lfloor \frac{an+b}{c} \rfloor-1}\sum_{x=0}^{n}[j<\lfloor \frac{ax+b}{c} \rfloor] \end{aligned} $$

为了方便,设 $m=\lfloor \dfrac{an+b}{c} \rfloor$,然后对于后面的东西,我们希望条件是和 $x$ 相关的(这样就可以丢掉一个求和符号)。因为 $j$ 是整数,可以这样化简:

$$ \begin{aligned} j<\lfloor \frac{ax+b}{c} \rfloor &\Rightarrow j+1\le \lfloor \frac{ax+b}{c} \rfloor\\ & \Rightarrow j+1\le \frac{ax+b}{c}\\ & \Rightarrow jc +c\le ax+b\\ & \Rightarrow x \ge \dfrac{jc+c-b}{a}\\ & \Rightarrow x \ge \lfloor \dfrac{jc+c-b}{a}\rfloor\\ & \Rightarrow x > \lfloor \dfrac{jc+c-b-1}{a}\rfloor \end{aligned} $$

最后一步是因为我们接下来要用到大于的形式比较好化简。代回原式有

$$ \begin{aligned} &=\sum_{j=0}^{m-1}\sum_{x=0}^{n}[x > \lfloor \dfrac{jc+c-b-1}{a}\rfloor]\\ &=\sum_{j=0}^{m-1}(n- \lfloor \dfrac{jc+c-b-1}{a}\rfloor)\\ &=nm-\sum_{j=0}^{m-1}\lfloor \dfrac{jc+c-b-1}{a}\rfloor\\ &=nm-f(c,c-b-1,a,m-1) \end{aligned} $$

这样就成功形成一个递归的形式了,观察到这个递归形式很像 $\gcd$ 算法,所以大佬们取名叫做类欧几里得。

Part $\mathrm{II}$ :$g,h$

这两个需要一起解,先设

$$ g(a,b,c,n)=\sum_{x=0}^{n}x\lfloor \frac{ax+b}{c} \rfloor \\ h(a,b,c,n)=\sum_{x=0}^{n}\lfloor \frac{ax+b}{c} \rfloor ^2 $$

注意和原题面的顺序不太一样。

$g$

老套路来一遍,就不加注释了

$$ \begin{aligned} g(a,b,c,n)&=\sum_{x=0}^{n}x\lfloor \frac{ax+b}{c} \rfloor\\ &=\sum_{x=0}^{n}x\lfloor \dfrac{(a \bmod c)x + (a-a\bmod c)x + (b\bmod c)+(b-b\bmod c)}{c}\rfloor\\ &=\sum_{x=0}^{n}x\lfloor \dfrac{(a \bmod c)x + (b\bmod c)}{c}\rfloor + \lfloor\dfrac{a}{c}\rfloor x^2+ \lfloor \dfrac{b}{c} \rfloor x\\ &=\dfrac{n(n+1)(2n+1)}{6}\lfloor\dfrac{a}{c}\rfloor + \dfrac{n(n+1)}{2}\lfloor \dfrac{b}{c} \rfloor + g(a\bmod c,b\bmod c,c,n) \end{aligned} $$

得到几乎一摸一样的取模形式。

具体计算也先尝试一样的套路试一下

$$ g(a,b,c,n)=\sum_{j=0}^{m-1}\sum_{x=0}^{n}x[x > \lfloor \dfrac{jc+c-b-1}{a}\rfloor] $$

这时候出现了一点小问题,后面多了一个 $x$ 如何处理?设 $t=\lfloor \dfrac{jc+c-b-1}{a}\rfloor$,我们可以调整一下求和范围把后面的东西干掉,即

$$ \begin{aligned} &=\sum_{j=0}^{m-1}\sum_{x=t+1}^{n}x\\ &=\sum_{j=0}^{m-1}\dfrac{(n+t+1)(n-t)}{2}\\ &=\dfrac{1}{2}\sum_{j=0}^{m-1}n(n+1)-t(t+1)\\ &=\dfrac{1}{2}(\sum_{j=0}^{m-1}n(n+1)-\sum_{j=0}^{m-1}(t^2+t))\\ &=\dfrac{1}{2}(mn(n+1)-\sum_{j=0}^{m-1}t^2-\sum_{j=0}^{m-1}t) \end{aligned} $$

回忆一下 $t=\lfloor \dfrac{jc+c-b-1}{a}\rfloor$,后面两项都可以化成我们已有的函数,即有了

$$ g(a,b,c,n)=\dfrac{1}{2}(mn(n+1)-h(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1)) $$

$h$

再来一遍!不过这次有一丢丢复杂。

$$ h(a,b,c,n)=\sum_{x=0}^{n}(\lfloor \dfrac{(a \bmod c)x + (b\bmod c)}{c}\rfloor + \lfloor\dfrac{a}{c}\rfloor x+ \lfloor \dfrac{b}{c} \rfloor)^2 $$

设 $s=\lfloor \dfrac{(a \bmod c)x + (b\bmod c)}{c}\rfloor$ 大力展开

$$ \begin{aligned} &=\sum_{x=0}^{n}(s^2+\lfloor\dfrac{a}{c}\rfloor^2 x^2+\lfloor \dfrac{b}{c} \rfloor^2+2\lfloor \dfrac{a}{c} \rfloor sx+2\lfloor \dfrac{b}{c} \rfloor s + 2\lfloor \dfrac{a}{c} \rfloor\lfloor \dfrac{b}{c} \rfloor)\\ &=\dfrac{n(n+1)(2n+1)}{6}\lfloor \dfrac{a}{c} \rfloor^2+(n+1)\lfloor \dfrac{b}{c} \rfloor^2+n(n+1)\lfloor \dfrac{a}{c} \rfloor\lfloor \dfrac{b}{c} \rfloor+\sum_{x=0}^{n}s^2+2\lfloor \dfrac{a}{c} \rfloor\sum_{x=0}^{n}xs+2\lfloor \dfrac{b}{c} \rfloor\sum_{x=0}^{n}s\\ &=\dfrac{n(n+1)(2n+1)}{6}\lfloor \dfrac{a}{c} \rfloor^2+(n+1)\lfloor \dfrac{b}{c} \rfloor^2+n(n+1)\lfloor \dfrac{a}{c} \rfloor\lfloor \dfrac{b}{c} \rfloor\\ &+h(a\bmod c,b\bmod c,c,n)+2\lfloor \dfrac{a}{c} \rfloor g(a\bmod c,b\bmod c,c,n)+2\lfloor \dfrac{b}{c}\rfloor f(a\bmod c,b\bmod c,c,n) \end{aligned} $$

那么只剩下最后一步了,还是尝试老套路,我们利用一个看起来很废话的东西:

$$ \alpha^2=\dfrac{\alpha(\alpha+1)}{2}\times 2 - \alpha $$

进行推导

$$ \begin{aligned} h(a,b,c,n)&=\sum_{x=0}^{n}(2\sum_{j=0}^{m-1}(j+1)-m)\\ &=2\sum_{x=0}^{n}\sum_{j=0}^{m-1}(j+1)-f(a,b,c,n)\\ &=2\sum_{j=0}^{m-1}(j+1)\sum_{x=0}^n[x>t]-f(a,b,c,n)\\ &=2\sum_{j=0}^{m-1}(j+1)(n-t)-f(a,b,c,n)\\ &=mn(m+1)-2g(c,c-b-1,a,m-1)-2f(c,c-b-1,a,m-1)-f(a,b,c,n) \end{aligned} $$

收工!

代码比较丑

#include<bits/stdc++.h>
using namespace std;
#define int long long 
int mod=998244353;
int qpow(int x,int y){
    int res=1;
    for(;y;y>>=1){
        if(y&1)res=res*x%mod;
        x=x*x%mod;
    }
    return res;
}
int inv2=qpow(2,mod-2),inv6=qpow(6,mod-2);
struct node{
    int f,g,h;
};
node calc(int a,int b,int c,int n){
    node res,tmp;
    if(a==0){
        res.f=(n+1)*(b/c)%mod;
        res.g=n*(n+1)%mod*inv2%mod*(b/c)%mod;
        res.h=(n+1)*(b/c)%mod*(b/c)%mod;
        return res;
    }
    if(a>=c||b>=c){
        tmp=calc(a%c,b%c,c,n);
        res.f=((n*(n+1)%mod*inv2%mod*(a/c)+(n+1)*(b/c)%mod)%mod+tmp.f)%mod;
        res.g=((n*(n+1)%mod*(2*n+1)%mod*inv6%mod*(a/c)%mod
        +n*(n+1)%mod*inv2%mod*(b/c)%mod)%mod
        +tmp.g)%mod;
        res.h=((((n*(n+1)%mod*(2*n+1)%mod*inv6%mod*(a/c)%mod*(a/c)%mod
        +(n+1)*(b/c)%mod*(b/c)%mod)%mod
        +n*(n+1)%mod*(a/c)%mod*(b/c)%mod)%mod
        +tmp.h+2*(a/c)%mod*tmp.g%mod)%mod
        +2*(b/c)%mod*tmp.f%mod)%mod;
        return res;
    }
    int m=((a*n)+b)/c;
    tmp=calc(c,c-b-1,a,m-1);
    res.f=(n*m%mod-tmp.f+mod)%mod;
    res.g=((n*m%mod*(n+1)%mod-tmp.h+mod)%mod-tmp.f+mod)%mod*inv2%mod;
    res.h=(((n*m%mod*(m+1)%mod-2*tmp.g%mod+mod)%mod-2*tmp.f%mod+mod)%mod-res.f+mod)%mod;
    return res;
}
int T,A,B,C,N;
signed main(){
    cin.tie(0),cout.tie(0),ios::sync_with_stdio(false);
    cin>>T;
    while(T--){
        cin>>N>>A>>B>>C;
        node R=calc(A,B,C,N);
        cout<<R.f<<" "<<R.h<<" "<<R.g<<"\n";
    }
    return 0;
}
posted @ 2023-08-04 23:02  Jryno1  阅读(15)  评论(0)    收藏  举报  来源