类欧几里得算法学习
模型
类欧几里得是用来快速的求以下式子:
- f ( a , b , c , n ) = ∑ i = 0 n [ a i + b c ] f(a,b,c,n)=\sum_{i=0}^n [\frac{ai+b}{c}] f(a,b,c,n)=∑i=0n[cai+b]
- g ( a , b , c , n ) = ∑ i = 0 n i × [ a i + b c ] g(a,b,c,n)=\sum_{i=0}^n i\times[\frac{ai+b}{c}] g(a,b,c,n)=∑i=0ni×[cai+b]
- h ( a , b , c , n ) = ∑ i = 0 n [ a i + b c ] 2 h(a,b,c,n)=\sum_{i=0}^n [\frac{ai+b}{c}]^2 h(a,b,c,n)=∑i=0n[cai+b]2
因其求解的方式与欧几里得算法类似,故被称为类欧几里得算法,同样时间复杂度为O(logn)。
计算 f(a,b,c,n)
当a>=c||b>=c
- ∑ i = 0 n [ a i + b c ] = ∑ i = 0 n [ a % c × i + b % c c ] + [ a c ] ∑ i + [ b c ] ∑ \sum_{i=0}^n [\frac{ai+b}{c}]=\sum_{i=0}^n [\frac{a\%c\times i+b\%c}{c}]+[\frac{a}{c}]\sum i+[\frac{b}{c}]\sum ∑i=0n[cai+b]=∑i=0n[ca%c×i+b%c]+[ca]∑i+[cb]∑
- f ( a , b , c , n ) = f ( a % c , b % c , c , n ) + [ a c ] ( n × ( n + 1 ) / 2 ) + [ b c ] × ( n + 1 ) f(a,b,c,n)=f(a\%c,b\%c,c,n)+[\frac{a}{c}](n\times (n+1)/2)+[\frac{b}{c}]\times (n+1) f(a,b,c,n)=f(a%c,b%c,c,n)+[ca](n×(n+1)/2)+[cb]×(n+1)
当a<c&&b<c
- 对于 ∑ i = 0 n [ a i + b c ] \sum_{i=0}^n [\frac{ai+b}{c}] ∑i=0n[cai+b],其还有一个几何意思是:求一条直线下方的整点数量。
- 设 m = ⌊ a n + b c ⌋ − 1 m=\lfloor \frac{an+b}{c}\rfloor-1 m=⌊can+b⌋−1
-
f
(
a
,
b
,
c
,
n
)
f(a,b,c,n)
f(a,b,c,n)
= ∑ i = 0 n [ a i + b c ] =\sum_{i=0}^n [\frac{ai+b}{c}] =∑i=0n[cai+b]
= ∑ i = 0 n ∑ j = 1 m + 1 [ j < = ⌊ a i + b c ⌋ ] =\sum_{i=0}^n\sum_{j=1}^{m+1}[j<=\lfloor \frac{ai+b}{c}\rfloor] =∑i=0n∑j=1m+1[j<=⌊cai+b⌋]
= ∑ j = 1 m + 1 ∑ i = 0 n [ j < = ⌊ a i + b c ⌋ ] =\sum_{j=1}^{m+1}\sum_{i=0}^{n}[j<=\lfloor \frac{ai+b}{c}\rfloor] =∑j=1m+1∑i=0n[j<=⌊cai+b⌋]
= ∑ j = 0 m ∑ i = 0 n [ j + 1 < = ⌊ a i + b c ⌋ ] =\sum_{j=0}^{m}\sum_{i=0}^{n}[j+1<=\lfloor \frac{ai+b}{c}\rfloor] =∑j=0m∑i=0n[j+1<=⌊cai+b⌋]
= ∑ j = 0 m ∑ i = 0 n [ j + 1 < = a i + b c ] =\sum_{j=0}^{m}\sum_{i=0}^{n}[j+1<=\frac{ai+b}{c}] =∑j=0m∑i=0n[j+1<=cai+b]
= ∑ j = 0 m ∑ i = 0 n [ j c + c < = a i + b ] =\sum_{j=0}^{m}\sum_{i=0}^{n}[jc+c<=ai+b] =∑j=0m∑i=0n[jc+c<=ai+b]
= ∑ j = 0 m ∑ i = 0 n [ a i > j c + c − b − 1 ] =\sum_{j=0}^{m}\sum_{i=0}^{n}[ai>jc+c-b-1] =∑j=0m∑i=0n[ai>jc+c−b−1]
= ∑ j = 0 m ∑ i = 0 n [ i > j c + c − b − 1 a ] =\sum_{j=0}^{m}\sum_{i=0}^{n}[i>\frac{jc+c-b-1}{a}] =∑j=0m∑i=0n[i>ajc+c−b−1]
= ∑ j = 0 m ( n − ⌊ j c + c − b − 1 a ⌋ ) =\sum_{j=0}^m(n-\lfloor\frac{jc+c-b-1}{a}\rfloor) =∑j=0m(n−⌊ajc+c−b−1⌋)
= ∑ i = 0 m n − f ( c , c − b − 1 , a , m ) =\sum_{i=0}^mn-f(c,c-b-1,a,m) =∑i=0mn−f(c,c−b−1,a,m)
当n=0:
f
(
a
,
b
,
c
,
n
)
=
[
b
c
]
f(a,b,c,n)=[\frac{b}{c}]
f(a,b,c,n)=[cb]
当a=0:
f
(
a
,
b
,
c
,
n
)
=
(
n
+
1
)
[
b
c
]
f(a,b,c,n)=(n+1) [\frac{b}{c}]
f(a,b,c,n)=(n+1)[cb]
代码如下:
ll f(ll a,ll b,ll c,ll n){
if(n==0)return b/c;
if(a==0)return b/c*(n+1);
if(a>=c&&b>=c)return f(a%c,b%c,c,n)+a/c*(n*n+1)/2+b/c*(n+1);
if(a<c||b<c)return (a*n+b)/c*n+f(c,c-b-1,a,(an+b)/c-1);
}
计算h(a,b,c,n)
当a>=c||b>=c
- h ( a , b , c , n ) = ∑ i = 0 n [ a i + b c ] 2 h(a,b,c,n)=\sum_{i=0}^n[\frac{ai+b}{c}]^2 h(a,b,c,n)=∑i=0n[cai+b]2
- = ∑ i = 0 n ( [ a c ] × i + [ b c ] + [ a % c × i + b % c c ] ) 2 =\sum_{i=0}^n([\frac{a}{c}]\times i+[\frac{b}{c}]+[\frac{a\%c\times i+b\%c}{c}])^2 =∑i=0n([ca]×i+[cb]+[ca%c×i+b%c])2
- 根据三个的完全平方数展开得到
- 原式 = ∑ i = 0 n ( [ a c ] × i ) 2 + ∑ i = 0 n ( [ b c ] ) 2 + ∑ i = 0 n ( [ a % c × i + b % c c ] ) 2 + 2 [ a c ] [ b c ] ∑ i = 0 n i + 2 [ a c ] ∑ i = 0 n i [ a % c × i + b % c c ] + 2 [ b c ] ∑ i = 0 n [ a % c × i + b % c c ] =\sum_{i=0}^n([\frac{a}{c}]\times i)^2+\sum_{i=0}^n([\frac{b}{c}])^2+\sum_{i=0}^n([\frac{a\%c\times i+b\%c}{c}])^2+2[\frac{a}{c}][\frac{b}{c}]\sum_{i=0}^ni+2[\frac{a}{c}]\sum_{i=0}^ni[\frac{a\%c\times i+b\%c}{c}]+2[\frac{b}{c}]\sum_{i=0}^n[\frac{a\%c\times i+b\%c}{c}] =∑i=0n([ca]×i)2+∑i=0n([cb])2+∑i=0n([ca%c×i+b%c])2+2[ca][cb]∑i=0ni+2[ca]∑i=0ni[ca%c×i+b%c]+2[cb]∑i=0n[ca%c×i+b%c]
- 化简得到 = [ a c ] 2 × ( n ( n + 1 ) ( 2 n + 1 ) ) 6 + [ b c ] 2 × ( n + 1 ) + h ( a % c , b % c , c , n ) + 2 [ a c ] [ b c ] × n ( n + 1 ) 2 + 2 [ a c ] g ( a % c , b % c , c , n ) + 2 [ b c ] f ( a % c , b % c , c , n ) =[\frac{a}{c}]^2\times \frac{(n(n+1)(2n+1))}{6}+[\frac{b}{c}]^2\times (n+1)+h(a\%c,b\%c,c,n)+2[\frac{a}{c}][\frac{b}{c}]\times \frac{n(n+1)}{2}+2[\frac{a}{c}]g(a\%c,b\%c,c,n)+2[\frac{b}{c}]f(a\%c,b\%c,c,n) =[ca]2×6(n(n+1)(2n+1))+[cb]2×(n+1)+h(a%c,b%c,c,n)+2[ca][cb]×2n(n+1)+2[ca]g(a%c,b%c,c,n)+2[cb]f(a%c,b%c,c,n)
当a<c&&b<c
- 同理根据证明直接写出最后结论,设 m = [ a n + b c ] − 1 m=[\frac{an+b}{c}]-1 m=[can+b]−1
- h ( a , b , c , n ) = n ( m + 1 ) 2 − 2 g ( c , c − b − 1 , a , m ) − f ( c , c − b − 1 , a , m ) h(a,b,c,n)=n(m+1)^2-2g(c,c-b-1,a,m)-f(c,c-b-1,a,m) h(a,b,c,n)=n(m+1)2−2g(c,c−b−1,a,m)−f(c,c−b−1,a,m)
当n=0:
h
(
a
,
b
,
c
,
n
)
=
[
b
c
]
2
h(a,b,c,n)=[\frac{b}{c}]^2
h(a,b,c,n)=[cb]2
当a=0:
h
(
a
,
b
,
c
,
n
)
=
(
n
+
1
)
×
[
b
c
]
2
h(a,b,c,n)=(n+1)\times [\frac{b}{c}]^2
h(a,b,c,n)=(n+1)×[cb]2
计算g(a,b,c,n)
当a>=c||b>=c
- g ( a , b , c , n ) = ∑ i = 0 n i [ a i + b c ] g(a,b,c,n)=\sum_{i=0}^ni[\frac{ai+b}{c}] g(a,b,c,n)=∑i=0ni[cai+b]
- = [ a c ] n ( n + 1 ) ( 2 n + 1 ) 6 + [ b c ] n ( n + 1 ) 2 + g ( a % c , b % c , c , n ) =[\frac{a}{c}]\frac{n(n+1)(2n+1)}{6}+[\frac{b}{c}]\frac{n(n+1)}{2}+g(a\%c,b\%c,c,n) =[ca]6n(n+1)(2n+1)+[cb]2n(n+1)+g(a%c,b%c,c,n)
当a<c&&b<c
- 设 m = [ a n + b c ] − 1 m=[\frac{an+b}{c}]-1 m=[can+b]−1
- g ( a , b , c , n ) = n ( n + 1 ) ( m + 1 ) − h ( c , c − b − 1 , a , m ) − f ( c , c − b − 1 , a . m ) 2 g(a,b,c,n)=\frac{n(n+1)(m+1)-h(c,c-b-1,a,m)-f(c,c-b-1,a.m)}{2} g(a,b,c,n)=2n(n+1)(m+1)−h(c,c−b−1,a,m)−f(c,c−b−1,a.m)
当n=0:
f
(
a
,
b
,
c
,
n
)
=
0
f(a,b,c,n)=0
f(a,b,c,n)=0
当a=0:
f
(
a
,
b
,
c
,
n
)
=
[
b
c
]
(
n
(
n
+
1
)
2
)
f(a,b,c,n)=[\frac{b}{c}](\frac{n(n+1)}{2})
f(a,b,c,n)=[cb](2n(n+1))
计算三者
由于后两者均需要其他形式,故递归的时候可以一起算比较快
模板如下:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll P = 998244353;
ll i2 = 499122177, i6 = 166374059;
struct data {
ll f, g, h;
};
data calc(ll n, ll a, ll b, ll c) {
ll ac = a / c, bc = b / c, m = (a * n + b) / c, n1 = n + 1, n21 = n * 2 + 1;
data ans;
ans.f=ans.g=ans.h=0;
if (a == 0) { // 迭代到最底层
ans.f = bc * n1 % P;
ans.g = bc * n % P * n1 % P * i2 % P;
ans.h = bc * bc % P * n1 % P;
return ans;
}
if (a >= c || b >= c) { // 取模
ans.f = n * n1 % P * i2 % P * ac % P + bc * n1 % P;
ans.g = ac * n % P * n1 % P * n21 % P * i6 % P + bc * n % P * n1 % P * i2 % P;
ans.h = ac * ac % P * n % P * n1 % P * n21 % P * i6 % P +
bc * bc % P * n1 % P + ac * bc % P * n % P * n1 % P;
ans.f %= P, ans.g %= P, ans.h %= P;
data e = calc(n, a % c, b % c, c); // 迭代
ans.h += e.h + 2 * bc % P * e.f % P + 2 * ac % P * e.g % P;
ans.g += e.g, ans.f += e.f;
ans.f %= P, ans.g %= P, ans.h %= P;
return ans;
} else {
data e = calc(m - 1, c, c - b - 1, a);
ans.f = n * m % P - e.f, ans.f = (ans.f % P + P) % P;
ans.g = m * n % P * n1 % P - e.h - e.f, ans.g = (ans.g * i2 % P + P) % P;
ans.h = n * m % P * (m + 1) % P - 2 * e.g - 2 * e.f - ans.f;
ans.h = (ans.h % P + P) % P;
return ans;
}
}
ll T, n, a, b, c;
int main() {
scanf("%lld", &T);
while (T--) {
scanf("%lld%lld%lld%lld", &n, &a, &b, &c);
data ans = calc(n, a, b, c);
printf("%lld %lld %lld\n", ans.f, ans.h, ans.g);
}
return 0;
}
例题
题目1:
- 题目描述:求 ∑ i = 0 H M − 1 ∣ i / H M − i m o d M / ∣ < = A \sum_{i=0}^{HM-1} |i/HM-i modM/|<=A ∑i=0HM−1∣i/HM−imodM/∣<=A