类欧几里得算法学习笔记

几个等式

其中 ⌊ ⌋ \lfloor \rfloor 表示向下取整, ⌈ ⌉ \lceil \rceil 表示向上取整。
a ≤ ⌊ b c ⌋ ⇔ a ⋅ c ≤ b a \le \lfloor { b \over c } \rfloor \Leftrightarrow a \cdot c \le b acbacb
a &lt; ⌈ b c ⌉ ⇔ a ⋅ c &lt; b a \lt \lceil { b \over c } \rceil \Leftrightarrow a \cdot c \lt b a<cbac<b
a ≥ ⌈ b c ⌉ ⇔ a ⋅ c ≥ b a \ge \lceil { b \over c } \rceil \Leftrightarrow a \cdot c \ge b acbacb
a &gt; ⌊ b c ⌋ ⇔ a ⋅ c &gt; b a \gt \lfloor { b \over c } \rfloor \Leftrightarrow a \cdot c \gt b a>cbac>b
上面四个式子可以这么理解:趋近可能取等,趋远不可能取等。
⌈ b c ⌉ ⇔ ⌊ b + c − 1 c ⌋ \lceil{ b \over c } \rceil \Leftrightarrow \lfloor{ b + c - 1 \over c } \rfloor cbcb+c1
⌊ b c ⌋ ⇔ ⌈ b − c + 1 c ⌉ \lfloor{ b \over c } \rfloor \Leftrightarrow \lceil{ b - c + 1 \over c } \rceil cbcbc+1
注:本篇博客若在算式中出现不等式,则该不等式表示为若成立值为一,若不成立值为零。

类欧几里得算法的简介

它本质上是一个函数,算法是用于快速求下面三个式子的值:
f ( a , b , c , n ) = ∑ i = 0 n ⌊ a ⋅ i + b c ⌋ f(a,b,c,n) = \sum_{i=0}^n \lfloor{ a \cdot i + b \over c }\rfloor f(a,b,c,n)=i=0ncai+b
g ( a , b , c , n ) = ∑ i = 0 n i ⋅ ⌊ a ⋅ i + b c ⌋ g(a,b,c,n) = \sum_{i=0}^n i \cdot \lfloor{ a \cdot i + b \over c }\rfloor g(a,b,c,n)=i=0nicai+b
h ( a , b , c , n ) = ∑ i = 0 n ⌊ a ⋅ i + b c ⌋ 2 h(a,b,c,n) = \sum_{i=0}^n \lfloor{ a \cdot i + b \over c }\rfloor^2 h(a,b,c,n)=i=0ncai+b2
由于求解过程与求解GCD一样涉及取模操作,因而时间复杂度相似,所以叫做类欧几里得算法。

求解f

f ( a , b , c , n ) = ∑ i = 0 n ⌊ a ⋅ i + b c ⌋ f(a,b,c,n) = \sum_{i=0}^n \lfloor{ a \cdot i + b \over c }\rfloor f(a,b,c,n)=i=0ncai+b
分类讨论
1. a = 0 a = 0 a=0 , 此时返回 ( n + 1 ) ⋅ ⌊ b c ⌋ (n + 1) \cdot \lfloor {b \over c}\rfloor (n+1)cb,以下情况 a a a均大于零(g,h同理)。
2. a ≥ c a \ge c ac b ≥ c b \ge c bc
⌊ a ⋅ i + b c ⌋ \lfloor{ a \cdot i + b \over c }\rfloor cai+b拆开,变成 ⌊ ( a % c ) ⋅ i + b % c c ⌋ \lfloor{ ( a \% c) \cdot i + b \% c \over c }\rfloor c(a%ci+b%c + ⌊ a c ⌋ ⋅ i \lfloor{a \over c} \rfloor \cdot i cai + ⌊ b c ⌋ \lfloor{ b \over c} \rfloor cb
f ( a , b , c , n ) ⇔ f ( a % c , b % c , c , n ) + n ⋅ ( n + 1 ) 2 ⋅ ⌊ a c ⌋ + ( n + 1 ) ⋅ ⌊ b c ⌋ f(a , b , c , n ) \Leftrightarrow f( a\%c,b\%c,c,n ) + { n \cdot ( n + 1 )\over 2} \cdot \lfloor{a \over c} \rfloor + (n + 1) \cdot \lfloor{ b \over c} \rfloor f(a,b,c,n)f(a%c,b%c,c,n)+2n(n+1)ca+(n+1)cb
3. a &lt; c a &lt; c a<c b &lt; c b &lt; c b<c
m = ⌊ a ⋅ n + b c ⌋ m = \lfloor { a \cdot n + b \over c } \rfloor m=can+b
f ( a , b , c , n ) = ∑ i = 0 n ⌊ a ⋅ i + b c ⌋ f(a,b,c,n) = \sum_{i=0}^n \lfloor{ a \cdot i + b \over c }\rfloor f(a,b,c,n)=i=0ncai+b转化为
f ( a , b , c , n ) = ∑ i = 0 n ∑ j = 1 m [ ⌊ a ⋅ i + b c ⌋ ≥ j ] f(a,b,c,n) = \sum_{i = 0}^n\sum_{j = 1}^m[\lfloor{ a \cdot i + b \over c} \rfloor \ge j] f(a,b,c,n)=i=0nj=1m[cai+bj]
这个在几何上,可以理解为引一条直线 y = a ⋅ x + b c y = { a \cdot x + b \over c} y=cax+b,它与平面直角坐标系和 y = n y = n y=n围成的直角梯形(也可能是直角三角形)内整点的数量(包括 y y y轴上的点,但不含 x x x轴上的点以及原点)。
函数图像

其实 y y y轴上没有整点,因为当 a &lt; c a &lt; c a<c b &lt; c b &lt; c b<c y y y轴上不会有整点。
好像扯开了-_-||,继续向下推,此时我们将求和符号上的参数做一些小小的变动,达到改变数值但次数不变的目的(其实是将 j j j改变范围的起止点但不改变范围大小):
f ( a , b , c , n ) = ∑ i = 0 n ∑ j = 0 m − 1 [ ⌊ a ⋅ i + b c ⌋ ≥ j + 1 ] f(a,b,c,n) = \sum_{i = 0}^n\sum_{j = 0}^{m -1}[\lfloor{ a \cdot i + b \over c} \rfloor \ge j + 1] f(a,b,c,n)=i=0nj=0m1[cai+bj+1]去掉分母 f ( a , b , c , n ) = ∑ i = 0 n ∑ j = 0 m − 1 [ a ⋅ i ≥ j ⋅ c + c − b ] f(a,b,c,n) = \sum_{i = 0}^n\sum_{j = 0}^{m -1}[a \cdot i \ge j \cdot c + c - b] f(a,b,c,n)=i=0nj=0m1[aijc+cb]去等 f ( a , b , c , n ) = ∑ i = 0 n ∑ j = 0 m − 1 [ a ⋅ i &gt; j ⋅ c + c − b − 1 ] f(a,b,c,n) = \sum_{i = 0}^n\sum_{j = 0}^{m -1}[a \cdot i \gt j \cdot c + c - b - 1] f(a,b,c,n)=i=0nj=0m1[ai>jc+cb1]两边同时除掉a f ( a , b , c , n ) = ∑ i = 0 n ∑ j = 0 m − 1 [ i &gt; j ⋅ c + c − b − 1 a ] f(a,b,c,n) = \sum_{i = 0}^n\sum_{j = 0}^{m -1}[i \gt { j \cdot c + c - b - 1 \over a }] f(a,b,c,n)=i=0nj=0m1[i>ajc+cb1]两个sigma符号可交换位置(严谨的数学证明我不会,但是脑补一下码两个for循环时,交换两个互不影响(起止点独立)的两个for循环时,不影响结果)。交换后再用 ∑ i = 0 n \sum_{i = 0}^n i=0n i i i吞掉(对于任意的 j j j,若使式子值为真, i i i至少为 ⌊ j ⋅ c + c − b − 1 a ⌋ + 1 \lfloor { j \cdot c + c - b - 1 \over a } \rfloor + 1 ajc+cb1+1,凭借这个思想可得到下面的式子,也可以用整点法)。 f ( a , b , c , n ) = ∑ j = 0 m − 1 ( n − ⌊ j ⋅ c + c − b − 1 a ⌋ ) f(a,b,c,n) = \sum_{j = 0}^{m -1}(n - \lfloor { j \cdot c + c - b - 1 \over a } \rfloor) f(a,b,c,n)=j=0m1(najc+cb1)观察到括号里面是 m m m n n n和一个f形式的求和,得到: f ( a , b , c , n ) = n ⋅ m − f ( c , c − b − 1 , a , m − 1 ) f(a,b,c,n) = n \cdot m - f( c , c - b - 1 , a , m - 1 ) f(a,b,c,n)=nmf(c,cb1,a,m1)此时第1,3个系数从 ( a , c ) (a , c) (a,c)变成 ( c , a % c ) (c , a \% c) (c,a%c),由以上三式可证,这一过程与欧几里得求GCD复杂度相似。

#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
inline ll f( ll a , ll b , ll c , ll n ) {
	if ( !a ) {
		return ( n + 1 ) * ( b / c );
	}
	if ( a > c || b > c ) {
		return ( n * ( n + 1 ) / 2 ) * ( a / c ) + ( n + 1 ) * ( b / c ) + f( a % c , b % c , c , n );
	}
	ll m = ( a * n + b ) / c;
	return n * m - f( c , c - b - 1 , a , m - 1 );
}
int main () {
	ll a , b , c , n;
	scanf("%lld%lld%lld%lld",&a,&b,&c,&n);
	printf("%lld",f( a , b , c , n ));
	return 0;
}

这里说明一下,g , h的推导都要用到f,g,h,下面两个要一口气学完。

求解g

首先,我们要求证(可能有大佬嫌我啰嗦了,可本蒟蒻就是不会 ) ∑ i = 0 n i 2 = n ⋅ ( n + 1 ) ⋅ ( 2 n + 1 ) 6 \sum_{i=0}^n i^2 = \frac{n \cdot(n+1)\cdot(2n+1)}{6} i=0ni2=6n(n+1)(2n+1)
首先,根据式子 ( n + 1 ) 3 = n 3 + 3 ⋅ n 2 + 3 ⋅ n + 1 (n + 1) ^ 3 = n ^ 3 + 3 \cdot n^2+3 \cdot n + 1 (n+1)3=n3+3n2+3n+1
得出: ( n + 1 ) 3 − n 3 = 3 ⋅ n 2 + 3 ⋅ n + 1 (n + 1) ^ 3 - n ^ 3 = 3 \cdot n ^ 2 + 3 \cdot n + 1 (n+1)3n3=3n2+3n+1以此类推: n 3 − ( n − 1 ) 3 = 3 ⋅ ( n − 1 ) 2 + 3 ⋅ ( n − 1 ) + 1 n ^ 3 - (n - 1) ^ 3 = 3 \cdot (n - 1) ^ 2 + 3 \cdot (n - 1) + 1 n3(n1)3=3(n1)2+3(n1)+1
… … … … … … … … … … … … … … ……………………………………
3 3 − 2 3 = 3 ⋅ 2 2 + 3 ⋅ 2 + 1 3 ^ 3 - 2 ^ 3 = 3 \cdot 2 ^ 2 + 3 \cdot 2 + 1 3323=322+32+1
2 3 − 1 3 = 3 ⋅ 1 2 + 3 ⋅ 1 + 1 2 ^ 3 - 1 ^ 3 = 3 \cdot 1 ^ 2 + 3 \cdot 1 + 1 2313=312+31+1
将上式左右两边相加得(为了方便,只加到 ( n − 1 ) 3 (n - 1)^3 (n1)3): ( n − 1 ) 3 − 1 = 3 ⋅ ( ∑ i = 0 n i 2 ) + 3 ∗ ( ∑ i = 0 n i ) + n (n - 1) ^ 3 - 1 = 3 \cdot ( \sum_{i=0}^n i^2 ) + 3 * ( \sum_{i=0}^n i) + n (n1)31=3(i=0ni2)+3(i=0ni)+n因为 ∑ i = 0 n i = n ⋅ ( n + 1 ) 2 \sum_{i=0}^n i = { n \cdot (n + 1) \over 2 } i=0ni=2n(n+1)得出 3 ∗ ∑ i = 0 n i 2 + 3 ⋅ ( n + 1 ) ⋅ n 2 + n = n 3 + 3 ⋅ n 2 + 3 ⋅ n 3 * \sum_{i=0}^n i^2 + { 3 \cdot ( n + 1) \cdot n \over 2} + n= n^3 + 3 \cdot n ^ 2 + 3 \cdot n 3i=0ni2+23(n+1)n+n=n3+3n2+3n
一口气推完后,就得到 ∑ i = 0 n i 2 = n ⋅ ( n + 1 ) ⋅ ( 2 n + 1 ) 6 \sum_{i=0}^n i^2 = \frac{n \cdot(n+1)\cdot(2n+1)}{6} i=0ni2=6n(n+1)(2n+1)
下面开始推 g g g

g ( a , b , c , n ) = ∑ i = 0 n i ⋅ ⌊ a ⋅ i + b c ⌋ g(a,b,c,n) = \sum_{i=0}^n i \cdot \lfloor{ a \cdot i + b \over c }\rfloor g(a,b,c,n)=i=0nicai+b
再次分类讨论
1. a = 0 a = 0 a=0时,到达边界,返回 n ⋅ ( n + 1 ) 2 ⋅ ⌊ b c ⌋ { n \cdot (n + 1) \over 2} \cdot \lfloor{b \over c} \rfloor 2n(n+1)cb
2. a ≥ c a \ge c ac b ≥ c b \ge c bc的情况,套上上面证的平方和公式,可得: g ( a , b , c , n ) = g ( a % c , b % c , c , n ) + n ⋅ ( n + 1 ) ⋅ ( 2 ⋅ n + 1 ) 6 ∗ ⌊ a c ⌋ + n ⋅ ( n + 1 ) 2 ∗ ⌊ b c ⌋ g(a,b,c,n) = g(a \% c ,b \% c,c,n) + { n \cdot (n + 1) \cdot (2 \cdot n + 1) \over 6} * \lfloor{ a \over c }\rfloor + { n \cdot (n + 1) \over 2 } * \lfloor{ b \over c }\rfloor g(a,b,c,n)=g(a%c,b%c,c,n)+6n(n+1)(2n+1)ca+2n(n+1)cb
3. a &lt; c a &lt; c a<c b &lt; c b &lt; c b<c时,根据 f f f的思路,可以得到: g ( a , b , c , n ) = ∑ i = 0 n i ⋅ ∑ j = 1 m [ ⌊ a ⋅ i + b c ⌋ ≥ j ] g(a , b , c , n) = \sum_{i=0}^n i \cdot \sum_{j=1}^m[ \lfloor { a \cdot i + b \over c } \rfloor \ge j ] g(a,b,c,n)=i=0nij=1m[cai+bj] m = ⌊ a ⋅ n + b c ⌋ m = \lfloor { a \cdot n + b \over c } \rfloor m=can+b(怕忘了 )
跳步得(手动滑稽 ): g ( a , b , c , n ) = ∑ i = 0 n i ⋅ ∑ j = 0 m − 1 [ i &gt; j ⋅ c + c − b − 1 a ] g(a , b , c , n) = \sum_{i=0}^n i \cdot \sum_{j=0}^{m - 1}[ i \gt { j \cdot c + c - b - 1 \over a } ] g(a,b,c,n)=i=0nij=0m1[i>ajc+cb1](不懂的请看回 f f f)
根据求 f f f时用到的整点思想,对于任意的 f f f,为了使表达式为真, i i i至少为 ⌊ j ⋅ c + c − b − 1 a ⌋ + 1 \lfloor { j \cdot c + c - b - 1 \over a }\rfloor + 1 ajc+cb1+1,其实这个上面已讲过了
t = ⌊ j ⋅ c + c − b − 1 a ⌋ t = \lfloor { j \cdot c + c - b - 1 \over a }\rfloor t=ajc+cb1 g ( a , b , c , n ) = ∑ j = 0 m − 1 ∑ i = t + 1 n i g(a , b , c , n) =\sum_{j=0}^{m - 1} \sum_{i=t + 1}^n i g(a,b,c,n)=j=0m1i=t+1ni不难发现这其实是一个等差数列 s n ′ = ( a 1 + a n ′ ) ⋅ n ′ 2 s_{n&#x27;} = { (a_1 + a_{n&#x27;}) \cdot n&#x27; \over 2 } sn=2(a1+an)n g ( a , b , c , n ) = ∑ j = 0 m − 1 ( t + 1 + n ) ⋅ ( n − t ) 2 g(a , b , c , n) =\sum_{j=0}^{m - 1} { (t + 1 + n) \cdot (n - t) \over 2} g(a,b,c,n)=j=0m12(t+1+n)(nt)
a 1 a_1 a1对应 t + 1 t + 1 t+1 a n ′ a_{n&#x27;} an对应 n n n n ′ n&#x27; n对应 ( n − t ) (n - t) (nt)
继续推 g ( a , b , c , n ) = n ⋅ m ⋅ ( 1 + n ) 2 − ∑ j = 0 m − 1 t 2 − ∑ j = 0 m − 1 t 2 2 g(a , b , c , n) = { n \cdot m \cdot (1 + n) \over 2 } - \sum_{j=0}^{m - 1}{t \over2 } - \sum_{j=0}^{m - 1}{t ^ 2 \over 2} g(a,b,c,n)=2nm(1+n)j=0m12tj=0m12t2
恢复 t t t的真面目可得: g ( a , b , c , n ) = n ⋅ m ⋅ ( 1 + n ) 2 − 1 2 ⋅ h ( c , c − b − 1 , a , m − 1 ) − 1 2 ⋅ f ( c , c − b − 1 , a , m − 1 ) g(a , b , c , n) = { n \cdot m \cdot (1 + n) \over 2 } - { 1 \over 2 } \cdot h( c , c - b - 1 , a , m - 1 ) - { 1 \over 2 } \cdot f(c , c - b - 1 , a , m - 1) g(a,b,c,n)=2nm(1+n)21h(c,cb1,a,m1)21f(c,cb1,a,m1)
这里要用到 h h h,所以我们继续推吧。

求解h

h ( a , b , c , n ) = ∑ i = 0 n ⌊ a ⋅ i + b c ⌋ 2 h(a,b,c,n) = \sum_{i=0}^n \lfloor{ a \cdot i + b \over c }\rfloor^2 h(a,b,c,n)=i=0ncai+b2
还是分类讨论
1. a = 0 a = 0 a=0时,边界,返回 ( n + 1 ) ⋅ ⌊ b c ⌋ 2 (n + 1) \cdot \lfloor { b\over c}\rfloor ^2 (n+1)cb2
2. a ≥ c a \ge c ac b ≥ c b \ge c bc,通过取模,不难得到 h ( a , b , c , n ) = ∑ i = 0 n ⌊ a ⋅ i + b c ⌋ 2 = ∑ i = 0 n [ ⌊ a c ⌋ ∗ i + ⌊ b c ⌋ + ( a % c c ∗ i + b % c c ) ] 2 h(a,b,c,n) = \sum_{i=0}^n \lfloor{ a \cdot i + b \over c }\rfloor^2 = \sum_{i=0}^n [\lfloor { a \over c }\rfloor * i + \lfloor { b \over c } \rfloor + ({a \% c \over c} * i + { b \% c \over c }) ]^2 h(a,b,c,n)=i=0ncai+b2=i=0n[cai+cb+(ca%ci+cb%c)]2这个式子比较复杂,先写一个简单的对应一下 ( x + y + z ) 2 = x 2 + y 2 + z 2 + 2 ⋅ x ⋅ y + 2 ⋅ x ⋅ z + 2 ⋅ y ⋅ z (x + y + z)^2 = x^2 + y^2 + z^2 + 2 \cdot x \cdot y + 2 \cdot x \cdot z + 2 \cdot y \cdot z (x+y+z)2=x2+y2+z2+2xy+2xz+2yz,用一一对应法,可得出上面的展开式为: h ( a , b , c , n ) = h ( a % c , b % c , c , n ) + n ⋅ ( n + 1 ) ⋅ ( 2 ⋅ n + 1 ) 6 ⋅ ⌊ a c ⌋ 2 + ( n + 1 ) ⋅ ⌊ b c ⌋ 2 + 2 ⋅ ⌊ b c ⌋ ⋅ f ( a % c , b % c , c , n ) + 2 ⋅ ⌊ a c ⌋ ⋅ g ( a % c , b % c , c , n ) + ⌊ a c ⌋ ⋅ ⌊ b c ⌋ ⋅ n ⋅ ( n + 1 ) h(a,b,c,n) = h(a \%c,b \% c,c,n) + {n \cdot ( n + 1 ) \cdot (2 \cdot n + 1) \over 6} \cdot \lfloor { a \over c }\rfloor^2 + (n + 1) \cdot \lfloor { b \over c }\rfloor^2 \\ + 2 \cdot \lfloor { b \over c }\rfloor \cdot f(a \%c,b \% c,c,n) + 2 \cdot \lfloor {a \over c} \rfloor \cdot g(a \%c,b \% c,c,n) + \lfloor {a \over c} \rfloor \cdot \lfloor {b \over c} \rfloor \cdot n \cdot (n + 1) h(a,b,c,n)=h(a%c,b%c,c,n)+6n(n+1)(2n+1)ca2+(n+1)cb2+2cbf(a%c,b%c,c,n)+2cag(a%c,b%c,c,n)+cacbn(n+1)
3. a &lt; c a \lt c a<c b &lt; c b \lt c b<c时,
考虑把狰狞的 x 2 x^2 x2拆一下,可得: x 2 = 2 ⋅ x ⋅ ( x + 1 ) 2 − x = 2 ⋅ ∑ i = 0 x i − x x^2 = 2 \cdot {x \cdot ( x + 1 ) \over 2} - x = 2 \cdot \sum_{i = 0}^x i - x x2=22x(x+1)x=2i=0xix利用这个拆开原式,并设 m = ⌊ a ⋅ n + b c ⌋ m = \lfloor {a \cdot n + b \over c} \rfloor m=can+b,可得: h ( a , b , c , n ) = ∑ i = 0 n ( ( 2 ⋅ ∑ j = 1 ⌊ a ⋅ i + b c ⌋ j ) − ⌊ a ⋅ i + b c ⌋ ) h(a,b,c,n) =\sum_{i = 0}^n ((2 \cdot \sum_{j = 1}^{ \lfloor {a \cdot i + b \over c}\rfloor} j) - \lfloor {a \cdot i + b \over c} \rfloor ) h(a,b,c,n)=i=0n((2j=1cai+bj)cai+b) 2 ⋅ ∑ j = 1 ⌊ a ⋅ i + b c ⌋ j 2 \cdot \sum_{j = 1}^{ \lfloor {a \cdot i + b \over c}\rfloor} j 2j=1cai+bj ⌊ a ⋅ i + b c ⌋ \lfloor {a \cdot i + b \over c} \rfloor cai+b拆开得(思想参考求 f f f时用的数形结合思想,上式是一列一列地统计整点,下式是一行一行地统计整点): h ( a , b , c , n ) = 2 ⋅ ( ∑ j = 0 m − 1 ( j + 1 ) ⋅ ∑ i = 0 n [ ⌊ a ⋅ i + b c ⌋ ≥ j + 1 ] ) − f ( a , b , c , n ) h(a,b,c,n) = 2 \cdot( \sum_{j = 0}^{m - 1} (j + 1) \cdot \sum_{i = 0}^n [\lfloor {a \cdot i + b \over c} \rfloor \ge j + 1 ] ) - f(a , b , c , n ) h(a,b,c,n)=2(j=0m1(j+1)i=0n[cai+bj+1])f(a,b,c,n) h ( a , b , c , n ) = 2 ⋅ ( ∑ j = 0 m − 1 j ⋅ ∑ i = 0 n [ ⌊ a ⋅ i + b c ⌋ ≥ j + 1 ] ) + 2 ⋅ ( ∑ j = 0 m − 1 ∑ i = 0 n [ ⌊ a ⋅ i + b c ⌋ ≥ j + 1 ] ) − f ( a , b , c , n ) h(a,b,c,n) = 2 \cdot( \sum_{j = 0}^{m - 1} j \cdot \sum_{i = 0}^n [\lfloor {a \cdot i + b \over c} \rfloor \ge j + 1 ] ) \\ + 2 \cdot( \sum_{j = 0}^{m - 1}\sum_{i = 0}^n [\lfloor {a \cdot i + b \over c} \rfloor \ge j + 1 ] ) - f(a , b , c , n ) h(a,b,c,n)=2(j=0m1ji=0n[cai+bj+1])+2(j=0m1i=0n[cai+bj+1])f(a,b,c,n)参照求 f f f的思路,跳步得o( ̄︶ ̄)o h ( a , b , c , n ) = 2 ⋅ ( ∑ j = 0 m − 1 j ⋅ ∑ i = 0 n [ i &gt; ⌊ j ⋅ c − c − b − 1 a ⌋ ] ) + 2 ⋅ ( ∑ j = 0 m − 1 ∑ i = 0 n [ i &gt; ⌊ j ⋅ c − c − b − 1 a ⌋ ] ) − f ( a , b , c , n ) h(a,b,c,n) = 2 \cdot( \sum_{j = 0}^{m - 1} j \cdot \sum_{i = 0}^n [i \gt \lfloor { j \cdot c - c - b - 1 \over a} \rfloor ] ) \\ + 2 \cdot( \sum_{j = 0}^{m - 1}\sum_{i = 0}^n [i \gt \lfloor { j \cdot c - c - b - 1 \over a} \rfloor ] ) - f(a , b , c , n ) h(a,b,c,n)=2(j=0m1ji=0n[i>ajccb1])+2(j=0m1i=0n[i>ajccb1])f(a,b,c,n)再推 h ( a , b , c , n ) = 2 ⋅ ( ∑ j = 0 m − 1 j ⋅ ( n − ⌊ j ⋅ c − c − b − 1 a ⌋ ) ) + 2 ⋅ ( ∑ j = 0 m − 1 ( n − ⌊ j ⋅ c − c − b − 1 a ⌋ ) ) − f ( a , b , c , n ) h(a,b,c,n) = 2 \cdot( \sum_{j = 0}^{m - 1} j \cdot (n - \lfloor { j \cdot c - c - b - 1 \over a} \rfloor) ) \\ + 2 \cdot( \sum_{j = 0}^{m - 1}(n - \lfloor { j \cdot c - c - b - 1 \over a} \rfloor) ) - f(a , b , c , n ) h(a,b,c,n)=2(j=0m1j(najccb1))+2(j=0m1(najccb1))f(a,b,c,n)得出: h ( a , b , c , n ) = m ⋅ ( m − 1 ) ⋅ n − 2 ⋅ g ( c , c − b − 1 , a , m − 1 ) + 2 ⋅ m ⋅ n − 2 ⋅ f ( c , c − b − 1 , a , m − 1 ) − f ( a , b , c , n ) h(a,b,c,n) = m \cdot (m - 1) \cdot n - 2 \cdot g( c , c - b - 1 , a , m - 1 ) \\ + 2 \cdot m \cdot n - 2 \cdot f(c , c - b - 1 , a , m - 1) - f(a , b ,c , n) h(a,b,c,n)=m(m1)n2g(c,cb1,a,m1)+2mn2f(c,cb1,a,m1)f(a,b,c,n)最终得出: h ( a , b , c , n ) = m ⋅ ( m + 1 ) ⋅ n − 2 ⋅ g ( c , c − b − 1 , a , m − 1 ) − 2 ⋅ f ( c , c − b − 1 , a , m − 1 ) − f ( a , b , c , n ) h(a,b,c,n) = m \cdot (m + 1) \cdot n - 2 \cdot g( c , c - b - 1 , a , m - 1 ) \\ - 2 \cdot f(c , c - b - 1 , a , m - 1) - f(a , b ,c , n) h(a,b,c,n)=m(m+1)n2g(c,cb1,a,m1)2f(c,cb1,a,m1)f(a,b,c,n)
终于推完了,长长地松一口气 ,\ ( ^ o ^ ) /~
g g g, h h h的实现比较复杂,因为要相互调用,最好用结构体维护。

板子

板子(f,g,h都有,三个愿望一次满足
这题数据较大,要对998244353取模,公式中有除以二除以六的操作,要使用拓展欧几里得求乘法逆元。
这题要勤取模,否则会WRONG。
示例代码

#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
#define mod  998244353
using namespace std;
struct node{
	ll f;
	ll g;
	ll h;
};
ll inv2 , inv6; 
inline void read( ll & res ) {
	res = 0;
	ll pd = 1;
	char aa = getchar();
	while ( aa < '0' || aa > '9' ) {
		if ( aa == '-' ) {
			pd = -pd;
		}
		aa = getchar();
	}
	while ( aa >= '0' && aa <= '9' ) {
		res = ( res << 1 ) + ( res << 3 ) + ( aa - '0' );
		aa = getchar();
	}
	res *= pd;
	return;
}
inline node solve( ll a , ll b , ll c , ll n ) {
	if ( !a ) {
		node ans;
		ans.f = (n + 1) % mod * ( b / c ) % mod;
		ans.g = n % mod * ( n + 1 ) % mod * inv2 % mod * ( b / c ) % mod;
		ans.h = ( n + 1 ) % mod * ( b / c ) % mod * ( b / c ) % mod;
		ans.f %= mod;
		ans.g %= mod;
		ans.h %= mod;
		return ans;
	}
	if ( a >= c || b >= c ) {
		node tem = solve( a % c , b % c , c , n );
		node ans;
		ans.f = (tem.f + n % mod * ( n + 1 ) % mod * inv2 % mod * ( a / c ) % mod) % mod + ( n + 1 ) % mod * ( b / c ) % mod;
		ans.g = (tem.g + n % mod * ( n + 1 ) % mod * ( 2 * n + 1 ) % mod * inv6 % mod * ( a / c ) % mod ) % mod 
		+ n % mod * ( n + 1 ) % mod * inv2 % mod * ( b / c ) % mod;
		ans.h = (((tem.h + n % mod * ( n + 1 ) % mod * ( 2 * n + 1 ) % mod * inv6 % mod * ( a / c ) % mod * ( a / c ) % mod) % mod 
		+ ( n + 1 ) % mod * ( b / c ) % mod * ( b / c ) % mod 
		+ 2 * ( b / c ) % mod * tem.f % mod) % mod + 2 * ( a / c ) % mod * tem.g % mod) % mod 
		+ ( a / c ) % mod * ( b / c ) % mod * n % mod * ( n + 1 ) % mod;
		ans.f %= mod;
		ans.g %= mod;
		ans.h %= mod;
		return ans;
	}
	ll m = ( ( a * n + b ) / c );
	node tem = solve( c , c - b - 1 , a , m - 1 );
	node ans;
	ans.f = n * ( m % mod ) % mod - tem.f;
	ans.f %= mod;
	ans.g = (n * ( m % mod ) % mod * ( 1 + n ) % mod * inv2 % mod) % mod - tem.h * inv2 % mod - tem.f * inv2 % mod;
	ans.h = (( m % mod ) * ( (m + 1) % mod ) % mod * n) % mod - 2 * tem.g % mod - 2 * tem.f % mod - ans.f;
	ans.g %= mod;
	ans.h %= mod;
	return ans;
}
inline ll exgcd( ll a , ll b , ll & x , ll & y ) {
	if ( !b ) {
		x = 1;
		y = 0;
		return a;
	}
	ll d = exgcd( b , a % b , x , y );
	ll tem = x;
	x = y;
	y = tem - a / b * y;
	return d;
}//类欧几里得里面有欧几里得(手动滑稽) 
int main () {
	ll temp;
	exgcd( 2 , mod , inv2 , temp );
	exgcd( 6 , mod , inv6 , temp );
	while ( inv2 < 0 ) {
		inv2 += mod;//乘法逆元 
	}
	while ( inv6 < 0 ) {
		inv6 += mod;//乘法逆元
	}
	//printf("%lld %lld",inv2,inv6);
	ll t , a , b , c , n;
	read(t);
	while ( t-- ) {
		read(n);
		read(a);
		read(b);
		read(c);
		node ans = solve( a , b , c , n );
		printf("%lld %lld %lld\n",( ans.f + mod )%mod,( ans.h + mod )%mod,( ans.g + mod )%mod);
	}
	return 0;
}

推荐好题

Earthquake
https://www.luogu.org/problem/P5171
Sum
https://www.luogu.org/problem/P5172
Fraction
https://www.luogu.org/problem/P5179

题解等我搞定了再贴吧

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值