类欧几里得算法

类欧几里得算法是用 O ( log ⁡ n ) O(\log n) O(logn) 时间求形如 ∑ i = 0 n ⌊ a i + b c ⌋ \sum\limits_{i=0}^n\left\lfloor\dfrac{ai+b}{c}\right \rfloor i=0ncai+b 的式子的答案的。 a , c > 0 , b ≥ 0 a,c>0,b\ge0 a,c>0,b0

类欧几里得算法

f ( n , a , b , c ) = ∑ i = 0 n ⌊ a i + b c ⌋ f(n,a,b,c)=\sum\limits_{i=0}^n\left\lfloor\dfrac{ai+b}{c}\right \rfloor f(n,a,b,c)=i=0ncai+b

我们可以把 a , b a,b a,b c c c 取模。
f ( n , a , b , c ) = ∑ i = 0 n ⌊ ( c ⌊ a c ⌋ + a   m o d   c ) i + c ⌊ b c ⌋ + b   m o d   c c ⌋ = ∑ i = 0 n ⌊ a c ⌋ i + ⌊ b c ⌋ + ⌊ ( a   m o d   c ) i + b   m o d   c c ⌋ = ⌊ a c ⌋ n ( n + 1 ) 2 + ( n + 1 ) ⌊ b c ⌋ + f ( n , a   m o d   c , b   m o d   c , c ) \begin{aligned} f(n,a,b,c)&=\sum\limits_{i=0}^n\left\lfloor\dfrac{(c\lfloor\frac ac\rfloor+a\bmod c)i+c\lfloor\frac bc\rfloor+b\bmod c}{c}\right \rfloor\\ &=\sum\limits_{i=0}^n\left\lfloor\dfrac ac\right\rfloor i+\left\lfloor\dfrac bc\right\rfloor+\left\lfloor\dfrac{(a\bmod c)i+b\bmod c}{c}\right \rfloor\\ &=\left\lfloor\dfrac ac\right\rfloor\dfrac{n(n+1)}{2}+(n+1)\left\lfloor\dfrac bc\right\rfloor+f(n,a\bmod c,b\bmod c,c)\\ \end{aligned} f(n,a,b,c)=i=0nc(cca+amodc)i+ccb+bmodc=i=0ncai+cb+c(amodc)i+bmodc=ca2n(n+1)+(n+1)cb+f(n,amodc,bmodc,c)

下面的 a , b a,b a,b 都是模过 c c c 的。

考虑继续化简变换。设 m = ⌊ a n + b c ⌋ m=\left\lfloor\dfrac{an+b}{c}\right \rfloor m=can+b

f ( n , a , b , c ) = ∑ i = 0 n ⌊ a i + b c ⌋ = ∑ i = 0 n ∑ j = 0 ⌊ a i + b c ⌋ − 1 1 = ∑ j = 0 m − 1 ∑ i = 0 n [ j < ⌊ a i + b c ⌋ ] = ∑ j = 0 m − 1 ∑ i = 0 n [ j + 1 ≤ ⌊ a i + b c ⌋ ] = ∑ j = 0 m − 1 ∑ i = 0 n [ j + 1 ≤ a i + b c ] = ∑ j = 0 m − 1 ∑ i = 0 n [ c j + c − b − 1 < a i ] = ∑ j = 0 m − 1 ∑ i = 0 n [ ⌊ c j + c − b − 1 a ⌋ < i ] = ∑ j = 0 m − 1 ( n − ⌊ c j + c − b − 1 a ⌋ ) = n m − f ( m − 1 , c , c − b − 1 , a ) \begin{aligned} f(n,a,b,c)&=\sum\limits_{i=0}^n\left\lfloor\frac{ai+b}{c}\right\rfloor\\ &=\sum\limits_{i=0}^n\sum\limits_{j=0}^{\left\lfloor\frac{ai+b}{c}\right \rfloor-1}1\\ &=\sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^n\left[j<\left\lfloor\dfrac{ai+b}{c}\right \rfloor\right]\\ &=\sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^n\left[j+1\le\left\lfloor\dfrac{ai+b}{c}\right \rfloor\right]\\ &=\sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^n\left[j+1\le\dfrac{ai+b}{c}\right]\\ &=\sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^n\left[cj+c-b-1< ai\right]\\ &=\sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^n\left[\left\lfloor\dfrac{cj+c-b-1}{a}\right\rfloor<i\right]\\ &=\sum\limits_{j=0}^{m-1}\left(n-\left\lfloor\dfrac{cj+c-b-1}{a}\right\rfloor\right)\\ &=nm-f(m-1,c,c-b-1,a)\\ \end{aligned} f(n,a,b,c)=i=0ncai+b=i=0nj=0cai+b11=j=0m1i=0n[j<cai+b]=j=0m1i=0n[j+1cai+b]=j=0m1i=0n[j+1cai+b]=j=0m1i=0n[cj+cb1<ai]=j=0m1i=0n[acj+cb1<i]=j=0m1(nacj+cb1)=nmf(m1,c,cb1,a)

这样,我们就得到一个递推式。发现 a , c a,c a,c 位置调换了,而且 a a a 还模了 c c c。这类似于辗转相除法,故时间复杂度是 O ( log ⁡ n ) O(\log n) O(logn) 的。

其实这个算法只有时间复杂度和欧几里得扯得上关系。

下面是参考实现代码

ll f(ll n,ll a,ll b,ll c)
{
    if(!a) return (n+1)*(b/c);
    if(a>=c||b>=c) return f(n,a%c,b%c,c)+n*(n+1)/2*(a/c)+(n+1)*(b/c);
    return (a*n+b)/c*n-f((a*n+b)/c-1,c,c-b-1,a);
}

拓展

∑ i = 0 n i ⌊ a i + b c ⌋ , ∑ i = 0 n ⌊ a i + b c ⌋ 2 \sum\limits_{i=0}^ni\left\lfloor\dfrac{ai+b}{c}\right \rfloor,\sum\limits_{i=0}^n\left\lfloor\dfrac{ai+b}{c}\right \rfloor^2 i=0nicai+b,i=0ncai+b2

g ( n , a , b , c ) = ∑ i = 0 n i ⌊ a i + b c ⌋ , h ( n , a , b , c ) = ∑ i = 0 n ⌊ a i + b c ⌋ 2 g(n,a,b,c)=\sum\limits_{i=0}^ni\left\lfloor\dfrac{ai+b}{c}\right \rfloor,h(n,a,b,c)=\sum\limits_{i=0}^n\left\lfloor\dfrac{ai+b}{c}\right \rfloor^2 g(n,a,b,c)=i=0nicai+b,h(n,a,b,c)=i=0ncai+b2

g g g:首先 a , b a,b a,b c c c 取模。类似得到
g ( n , a , b , c ) = ∑ i = 0 n i ⌊ ( c ⌊ a c ⌋ + a   m o d   c ) i + c ⌊ b c ⌋ + b   m o d   c c ⌋ = ∑ i = 0 n ( i 2 ⌊ a c ⌋ + i ⌊ b c ⌋ + i ⌊ ( a   m o d   c ) i + b   m o d   c c ⌋ ) = ⌊ a c ⌋ n ( n + 1 ) ( 2 n + 1 ) 6 + ⌊ b c ⌋ n ( n + 1 ) 2 + g ( n , a   m o d   c , b   m o d   c , c ) \begin{aligned} g(n,a,b,c)&=\sum\limits_{i=0}^ni\left\lfloor\dfrac{(c\lfloor\frac ac\rfloor+a\bmod c)i+c\lfloor\frac bc\rfloor+b\bmod c}{c}\right \rfloor\\ &=\sum\limits_{i=0}^n\left(i^2\left\lfloor\frac ac\right\rfloor+i\left\lfloor\frac bc\right\rfloor+i\left\lfloor\dfrac{(a\bmod c)i+b\bmod c}{c}\right \rfloor\right)\\ &=\left\lfloor\frac ac\right\rfloor\dfrac{n(n+1)(2n+1)}{6}+\left\lfloor\frac bc\right\rfloor\dfrac{n(n+1)}{2}+g(n,a\bmod c,b\bmod c,c) \end{aligned} g(n,a,b,c)=i=0nic(cca+amodc)i+ccb+bmodc=i=0n(i2ca+icb+ic(amodc)i+bmodc)=ca6n(n+1)(2n+1)+cb2n(n+1)+g(n,amodc,bmodc,c)

p = ⌊ c j + c − b − 1 a ⌋ p=\left\lfloor\dfrac{cj+c-b-1}{a}\right\rfloor p=acj+cb1

g ( n , a , b , c ) = ∑ i = 0 n i ⌊ a i + b c ⌋ = ∑ i = 0 n ∑ j = 0 ⌊ a i + b c ⌋ − 1 i = ∑ j = 0 m − 1 ∑ i = 0 n [ j < ⌊ a i + b c ⌋ ] i = ∑ j = 0 m − 1 ∑ i = 0 n [ j + 1 ≤ a i + b c ] i = ∑ j = 0 m − 1 ∑ i = 0 n [ p < i ] i = ∑ j = 0 m − 1 ( n + p + 1 ) ( n − p ) 2 = 1 2 ∑ j = 0 m − 1 ( n 2 + n − p 2 − p ) = 1 2 ( n m ( n + 1 ) − ∑ j = 0 m − 1 p 2 − ∑ j = 0 m − 1 p ) = 1 2 ( n m ( n + 1 ) − h ( m − 1 , c , c − b − 1 , a ) − f ( m − 1 , c , c − b − 1 , a ) ) \begin{aligned} g(n,a,b,c)&=\sum\limits_{i=0}^ni\left\lfloor\dfrac{ai+b}{c}\right \rfloor\\ &=\sum\limits_{i=0}^n\sum\limits_{j=0}^{\left\lfloor\frac{ai+b}{c}\right \rfloor-1}i\\ &=\sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^n\left[j<\left\lfloor\dfrac{ai+b}{c}\right \rfloor\right]i\\ &=\sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^n\left[j+1\le\dfrac{ai+b}{c}\right]i\\ &=\sum\limits_{j=0}^{m-1}\sum\limits_{i=0}^n\left[p<i\right]i\\ &=\sum\limits_{j=0}^{m-1}\dfrac{(n+p+1)(n-p)}{2}\\ &=\dfrac12\sum\limits_{j=0}^{m-1}\left(n^2+n-p^2-p\right)\\ &=\dfrac12\left(nm(n+1)-\sum\limits_{j=0}^{m-1}p^2-\sum\limits_{j=0}^{m-1}p\right)\\ &=\dfrac12\left(nm(n+1)-h(m-1,c,c-b-1,a)-f(m-1,c,c-b-1,a)\right) \end{aligned} g(n,a,b,c)=i=0nicai+b=i=0nj=0cai+b1i=j=0m1i=0n[j<cai+b]i=j=0m1i=0n[j+1cai+b]i=j=0m1i=0n[p<i]i=j=0m12(n+p+1)(np)=21j=0m1(n2+np2p)=21(nm(n+1)j=0m1p2j=0m1p)=21(nm(n+1)h(m1,c,cb1,a)f(m1,c,cb1,a))

发现这里 g g g 函数的递归调用了 h h h,接下来求 h h h a , b a,b a,b 还是要对 c c c 取模。

h ( n , a , b , c ) = ∑ i = 0 n ⌊ ( c ⌊ a c ⌋ + a   m o d   c ) i + c ⌊ b c ⌋ + b   m o d   c c ⌋ 2 = ∑ i = 0 n ( i ⌊ a c ⌋ + ⌊ b c ⌋ + ⌊ ( a   m o d   c ) i + b   m o d   c c ⌋ ) 2 = ∑ i = 0 n ( i 2 ⌊ a c ⌋ 2 + ⌊ b c ⌋ 2 + ⌊ ( a   m o d   c ) i + b   m o d   c c ⌋ 2 + 2 i ⌊ a c ⌋ ⌊ b c ⌋ + 2 i ⌊ a c ⌋ ⌊ ( a   m o d   c ) i + b   m o d   c c ⌋ + 2 ⌊ b c ⌋ ⌊ ( a   m o d   c ) i + b   m o d   c c ⌋ ) = ⌊ a c ⌋ 2 n ( n + 1 ) ( 2 n + 1 ) 6 + ⌊ b c ⌋ 2 ( n + 1 ) + ⌊ a c ⌋ ⌊ b c ⌋ n ( n + 1 ) + h ( n , a   m o d   c , b   m o d   c , c ) + 2 ⌊ a c ⌋ g ( n , a   m o d   c , b   m o d   c , c ) + 2 ⌊ b c ⌋ f ( n , a   m o d   c , b   m o d   c , c ) \begin{aligned} h(n,a,b,c)&=\sum\limits_{i=0}^n\left\lfloor\dfrac{(c\lfloor\frac ac\rfloor+a\bmod c)i+c\lfloor\frac bc\rfloor+b\bmod c}{c}\right \rfloor^2\\ &=\sum\limits_{i=0}^n\left(i\left\lfloor\frac ac\right\rfloor+\left\lfloor\frac bc\right\rfloor+\left\lfloor\dfrac{(a\bmod c)i+b\bmod c}{c}\right \rfloor\right)^2\\ &=\sum\limits_{i=0}^n\left(i^2\left\lfloor\frac ac\right\rfloor^2+\left\lfloor\frac bc\right\rfloor^2+\left\lfloor\dfrac{(a\bmod c)i+b\bmod c}{c}\right \rfloor^2+2i\left\lfloor\frac ac\right\rfloor\left\lfloor\frac bc\right\rfloor+2i\left\lfloor\frac ac\right\rfloor\left\lfloor\dfrac{(a\bmod c)i+b\bmod c}{c}\right \rfloor+2\left\lfloor\frac bc\right\rfloor\left\lfloor\dfrac{(a\bmod c)i+b\bmod c}{c}\right\rfloor\right)\\ &=\left\lfloor\frac ac\right\rfloor^2\dfrac{n(n+1)(2n+1)}{6}+\left\lfloor\frac bc\right\rfloor^2(n+1)+\left\lfloor\frac ac\right\rfloor\left\lfloor\frac bc\right\rfloor n(n+1)+h(n,a\bmod c,b\bmod c,c)+2\left\lfloor\frac ac\right\rfloor g(n,a\bmod c,b\bmod c,c)+2\left\lfloor\frac bc\right\rfloor f(n,a\bmod c,b\bmod c,c) \end{aligned} h(n,a,b,c)=i=0nc(cca+amodc)i+ccb+bmodc2=i=0n(ica+cb+c(amodc)i+bmodc)2=i=0n(i2ca2+cb2+c(amodc)i+bmodc2+2icacb+2icac(amodc)i+bmodc+2cbc(amodc)i+bmodc)=ca26n(n+1)(2n+1)+cb2(n+1)+cacbn(n+1)+h(n,amodc,bmodc,c)+2cag(n,amodc,bmodc,c)+2cbf(n,amodc,bmodc,c)

虽然挺复杂,但还是能表示。

继续求值,和上面差不多,但是有点不一样。

如果要把 ⌊ a i + b c ⌋ 2 \left\lfloor\dfrac{ai+b}{c}\right\rfloor^2 cai+b2 像上面一样转化,就变成 ∑ j = 0 ⌊ a i + b c ⌋ − 1 ∑ j = 0 ⌊ a i + b c ⌋ − 1 1 \sum\limits_{j=0}^{\left\lfloor\frac{ai+b}{c}\right \rfloor-1}\sum\limits_{j=0}^{\left\lfloor\frac{ai+b}{c}\right \rfloor-1}1 j=0cai+b1j=0cai+b11,有两个求和符号,不好处理,考虑换一种表示方式。下面的 m , p m,p m,p 和上面的是一样的。

由于 n 2 = 2 ⋅ n ( n + 1 ) 2 − n = 2 ∑ i = 1 n i − n n^2=2\cdot \dfrac{n(n+1)}{2}-n=2\sum\limits_{i=1}^ni-n n2=22n(n+1)n=2i=1nin

所以
h ( n , a , b , c ) = ∑ i = 0 n ⌊ a i + b c ⌋ 2 = ∑ i = 0 n ( 2 ∑ j = 1 ⌊ a i + b c ⌋ j − ⌊ a i + b c ⌋ ) = 2 ∑ i = 0 n ∑ j = 0 ⌊ a i + b c ⌋ − 1 ( j + 1 ) − f ( n , a , b , c ) \begin{aligned} h(n,a,b,c)&=\sum\limits_{i=0}^n\left\lfloor\dfrac{ai+b}{c}\right\rfloor^2\\ &=\sum\limits_{i=0}^n\left(2\sum\limits_{j=1}^{\left\lfloor\frac{ai+b}{c}\right\rfloor}j-\left\lfloor\dfrac{ai+b}{c}\right\rfloor\right)\\ &=2\sum\limits_{i=0}^n\sum\limits_{j=0}^{\left\lfloor\frac{ai+b}{c}\right\rfloor-1}(j+1)-f(n,a,b,c) \end{aligned} h(n,a,b,c)=i=0ncai+b2=i=0n 2j=1cai+bjcai+b =2i=0nj=0cai+b1(j+1)f(n,a,b,c)

只看前面
= 2 ∑ i = 0 n ∑ j = 0 ⌊ a i + b c ⌋ − 1 ( j + 1 ) = 2 ∑ j = 0 m − 1 ( j + 1 ) ∑ i = 0 n [ j < ⌊ a i + b c ⌋ ] = 2 ∑ j = 0 m − 1 ( j + 1 ) ∑ i = 0 n [ p < i ] = 2 ∑ j = 0 m − 1 ( j + 1 ) ( n − p ) = 2 ∑ j = 0 m − 1 ( n ( j + 1 ) − p j − p ) = n m ( m + 1 ) − 2 g ( m − 1 , c , c − b − 1 , a ) − 2 f ( m − 1 , c , c − b − 1 , a ) \begin{aligned} &=2\sum\limits_{i=0}^n\sum\limits_{j=0}^{\left\lfloor\frac{ai+b}{c}\right\rfloor-1}(j+1)\\ &=2\sum\limits_{j=0}^{m-1}(j+1)\sum\limits_{i=0}^{n}\left[j<\left\lfloor\dfrac{ai+b}{c}\right\rfloor\right]\\ &=2\sum\limits_{j=0}^{m-1}(j+1)\sum\limits_{i=0}^{n}\left[p<i\right]\\ &=2\sum\limits_{j=0}^{m-1}(j+1)(n-p)\\ &=2\sum\limits_{j=0}^{m-1}\left(n(j+1)-pj-p\right)\\ &=nm(m+1)-2g(m-1,c,c-b-1,a)-2f(m-1,c,c-b-1,a) \end{aligned} =2i=0nj=0cai+b1(j+1)=2j=0m1(j+1)i=0n[j<cai+b]=2j=0m1(j+1)i=0n[p<i]=2j=0m1(j+1)(np)=2j=0m1(n(j+1)pjp)=nm(m+1)2g(m1,c,cb1,a)2f(m1,c,cb1,a)

h ( n , a , b , c ) = n m 2 − 2 g ( m − 1 , c , c − b − 1 , a ) − f ( m − 1 , c , c − b − 1 , a ) h(n,a,b,c)=nm^2-2g(m-1,c,c-b-1,a)-f(m-1,c,c-b-1,a) h(n,a,b,c)=nm22g(m1,c,cb1,a)f(m1,c,cb1,a)

f , g , h f,g,h f,g,h 相互调用,但是里面参数变化是一致的。所以可以同时递归求 f , g , h f,g,h f,g,h,时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)

例题 P5170 【模板】类欧几里得算法

参考代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353,inv2=499122177,inv6=166374059;
ll n,a,b,c;
struct node
{
    ll f,g,h;
};
node solve(ll n,ll a,ll b,ll c)
{
    if(!a) return {b/c*(n+1)%mod,b/c*n%mod*(n+1)%mod*inv2%mod,(b/c)*(b/c)%mod*(n+1)%mod};
    if(a>=c||b>=c){
        node x=solve(n,a%c,b%c,c);
        x.h=((a/c)*(a/c)%mod*n%mod*(n+1)%mod*(2*n+1)%mod*inv6%mod+(b/c)*(b/c)%mod*(n+1)%mod+(a/c)*(b/c)%mod*n%mod*(n+1)%mod+x.h+a/c*2*x.g+b/c*2*x.f)%mod;
        x.f=(x.f+a/c*n%mod*(n+1)%mod*inv2%mod+b/c*(n+1))%mod;
        x.g=(x.g+a/c*n%mod*(n+1)%mod*(2*n+1)%mod*inv6%mod+b/c*n%mod*(n+1)%mod*inv2)%mod;
        return x;
    }
    ll m=(a*n+b)/c;
    node x=solve(m-1,c,c-b-1,a),ans;
    ans.f=(n*m%mod-x.f+mod)%mod;
    ans.g=inv2*(n*m%mod*(n+1)%mod-x.h-x.f+2*mod)%mod;
    ans.h=(n*m%mod*m%mod-2*x.g-x.f+4*mod)%mod;
    return ans;
}
int main()
{
    int t;
    cin>>t;
    while(t--){
        scanf("%lld%lld%lld%lld",&n,&a,&b,&c);
        node ans=solve(n,a,b,c);
        printf("%lld %lld %lld\n",ans.f,ans.h,ans.g);
    }
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值