文章目录
如果学过数学,可以从 3.类欧几里得
开始看。
1.概述
用于解决有关等差数列每一项的除法下取整的值。具体来说,有三种。
f ( a , b , c , n ) = ∑ x = 0 n − 1 ⌊ a x + b c ⌋ f(a,b,c,n)=\sum_{x=0}^{n-1}\left\lfloor\frac{ax+b}{c}\right\rfloor f(a,b,c,n)=x=0∑n−1⌊cax+b⌋
g ( a , b , c , n ) = ∑ x = 0 n − 1 ⌊ a x + b c ⌋ ⋅ x g(a,b,c,n)=\sum_{x=0}^{n-1}\left\lfloor\frac{ax+b}{c}\right\rfloor\cdot x g(a,b,c,n)=x=0∑n−1⌊cax+b⌋⋅x
h ( a , b , c , n ) = ∑ x = 0 n − 1 ⌊ a x + b c ⌋ 2 h(a,b,c,n)=\sum_{x=0}^{n-1}\left\lfloor\frac{ax+b}{c}\right\rfloor^2 h(a,b,c,n)=x=0∑n−1⌊cax+b⌋2
2.数学定理
如果没有特殊说明,认为所有未知数为整数。
2.0.拐弯抹角
a = m c + r ( 0 ≤ r < c ) ⇔ m = ⌊ a c ⌋ , r = a m o d c a=mc+r\;(0\le r<c)\\ \Leftrightarrow m=\left\lfloor\frac{a}{c}\right\rfloor,\;r=a\bmod c a=mc+r(0≤r<c)⇔m=⌊ca⌋,r=amodc
类似地,我们有
a
=
m
c
+
r
(
−
c
<
r
≤
0
)
⇔
m
=
⌈
a
c
⌉
\begin{aligned} a&=mc+r\;(-c<r\le 0)\\ \Leftrightarrow m&=\left\lceil\frac{a}{c}\right\rceil \end{aligned}
a⇔m=mc+r(−c<r≤0)=⌈ca⌉
在后面的叙述中,该定理在被使用之前,可能不会明确指出。
2.1.上下不安
此成语读作shàng xià bù ān
⌊ a c ⌋ = ⌈ a − ( c − 1 ) c ⌉ \left\lfloor\frac{a}{c}\right\rfloor=\left\lceil\frac{a-(c-1)}{c}\right\rceil ⌊ca⌋=⌈ca−(c−1)⌉
也即, ⌊ a + ( c − 1 ) c ⌋ = ⌈ a c ⌉ \left\lfloor\frac{a+(c-1)}{c}\right\rfloor=\left\lceil\frac{a}{c}\right\rceil ⌊ca+(c−1)⌋=⌈ca⌉
证明非常简单。不妨设 a = m c + r ( 0 ≤ r < c ) a=mc+r\;(0\le r < c) a=mc+r(0≤r<c),此时 m = ⌊ a c ⌋ m=\left\lfloor\frac{a}{c}\right\rfloor m=⌊ca⌋ 。
令 r ′ = r − ( c − 1 ) r'=r-(c-1) r′=r−(c−1),可知 a − ( c − 1 ) = m c + r ′ ( − c < r ′ ≤ 0 ) a-(c-1)=mc+r'\;(-c<r'\le 0) a−(c−1)=mc+r′(−c<r′≤0),得 m = ⌈ a − ( c − 1 ) c ⌉ m=\left\lceil\frac{a-(c-1)}{c}\right\rceil m=⌈ca−(c−1)⌉ 。
所以第一个等式成立。第二个等式与第一个等式是等价的。
2.2.整数分离
∀ x ∈ R , ⌊ x + k ⌋ = ⌊ x ⌋ + k \forall x\in\R,\;\left\lfloor x+k\right\rfloor=\left\lfloor x\right\rfloor+k ∀x∈R,⌊x+k⌋=⌊x⌋+k
正确性是显然的。
2.3.乘积分离
⌊ a x c ⌋ = ⌊ ( a m o d c ) ⋅ x c ⌋ + ⌊ a c ⌋ ⋅ x \left\lfloor\frac{ax}{c}\right\rfloor=\left\lfloor\frac{(a\bmod c)\cdot x}{c}\right\rfloor+\left\lfloor\frac{a}{c}\right\rfloor\cdot x ⌊cax⌋=⌊c(amodc)⋅x⌋+⌊ca⌋⋅x
其实就是 2.2.整数分离
的应用。设
a
=
m
c
+
r
(
0
≤
r
<
c
)
a=mc+r\;(0\le r < c)
a=mc+r(0≤r<c),则
⌊
a
x
c
⌋
=
⌊
(
m
c
+
r
)
x
c
⌋
=
⌊
m
x
+
r
x
c
⌋
=
m
x
+
⌊
r
x
c
⌋
\left\lfloor\frac{ax}{c}\right\rfloor=\left\lfloor\frac{(mc+r)x}{c}\right\rfloor=\left\lfloor mx+\frac{rx}{c}\right\rfloor=mx+\left\lfloor\frac{rx}{c}\right\rfloor
⌊cax⌋=⌊c(mc+r)x⌋=⌊mx+crx⌋=mx+⌊crx⌋ 。
我们又知道 m = ⌊ a c ⌋ , r = a m o d c m=\left\lfloor\frac{a}{c}\right\rfloor,\;r=a\bmod c m=⌊ca⌋,r=amodc,替换即可。
2.4.误差范围
∀ x ∈ R , a ≤ x ⇔ a ≤ ⌊ x ⌋ \forall x\in\R,\;a\le x\Leftrightarrow a\le\left\lfloor x\right\rfloor ∀x∈R,a≤x⇔a≤⌊x⌋
类似地,我们有
∀
x
∈
R
,
a
≥
x
⇔
a
≥
⌈
x
⌉
\forall x\in\R,\;a\ge x\Leftrightarrow a\ge\lceil x\rceil
∀x∈R,a≥x⇔a≥⌈x⌉
正确性是显然的:只需要证明 a a a 合法的取值既没有变少,也没有变多即可。
2.5.布尔计算
∑ j = 1 n [ j ≤ a ] = ∑ j = 0 n − 1 [ j < a ] = min ( n , a ) \sum_{j=1}^{n}[j\le a]=\sum_{j=0}^{n-1}[j<a]=\min(n,a) j=1∑n[j≤a]=j=0∑n−1[j<a]=min(n,a)
3.类欧几里得
3.1.求 f f f
别忘了
f
f
f 的定义,
f
(
a
,
b
,
c
,
n
)
=
∑
x
=
0
n
−
1
⌊
a
x
+
b
c
⌋
f(a,b,c,n)=\sum_{x=0}^{n-1}\left\lfloor\frac{ax+b}{c}\right\rfloor
f(a,b,c,n)=x=0∑n−1⌊cax+b⌋
很明显,这是最简单的一个。并且它会是 g g g 和 h h h 的基础。
3.1.0.规定
认为 a > 0 a>0 a>0,因为在其他情况下:
- 当 a = 0 a=0 a=0 时,显然可直接得到 f ( a , b , c , n ) = n ⌊ b c ⌋ f(a,b,c,n)=n\left\lfloor\frac{b}{c}\right\rfloor f(a,b,c,n)=n⌊cb⌋ 。
- 当 a < 0 a<0 a<0 时,根据其本质,我们知道 f ( a , b , c , n ) = f [ − a , ( n − 1 ) a + b , c , n ] f(a,b,c,n)=f[-a,(n-1)a+b,c,n] f(a,b,c,n)=f[−a,(n−1)a+b,c,n] 。
3.1.1.情况一
当
a
≥
c
a\ge c
a≥c 或者
b
≥
c
b\ge c
b≥c 时,根据 2.3.乘积分离
(顺便在
b
b
b 身上使用 2.2.整数分离
),我们可以发现,
f ( a , b , c , n ) = ∑ x = 0 n − 1 [ ⌊ ( a m o d c ) x + ( b m o d c ) c ⌋ + x ⌊ a c ⌋ + ⌊ b c ⌋ ] = f ( a m o d c , b m o d c , c , n ) + n ( n − 1 ) 2 ⌊ a c ⌋ + n ⌊ b c ⌋ \begin{aligned} f(a,b,c,n)&=\sum_{x=0}^{n-1}\left[\left\lfloor\frac{(a\bmod c)x+(b\bmod c)}{c}\right\rfloor+x\left\lfloor\frac{a}{c}\right\rfloor+\left\lfloor\frac{b}{c}\right\rfloor\right]\\ &=f(a\bmod c,b\bmod c,c,n)+\frac{n(n-1)}{2}\left\lfloor\frac{a}{c}\right\rfloor+n\left\lfloor\frac{b}{c}\right\rfloor \end{aligned} f(a,b,c,n)=x=0∑n−1[⌊c(amodc)x+(bmodc)⌋+x⌊ca⌋+⌊cb⌋]=f(amodc,bmodc,c,n)+2n(n−1)⌊ca⌋+n⌊cb⌋
3.1.2.情况二
当
0
<
a
<
c
0<a<c
0<a<c 并且
b
<
c
b<c
b<c 时,令
m
=
⌊
(
n
−
1
)
a
+
b
c
⌋
m=\left\lfloor\frac{(n-1)a+b}{c}\right\rfloor
m=⌊c(n−1)a+b⌋
(顺便叨叨一句,这个 m m m 在后面会很常见,都是这个定义。)
显然
min
(
⌊
a
x
+
b
c
⌋
,
m
)
=
⌊
a
x
+
b
c
⌋
\min(\left\lfloor\frac{ax+b}{c}\right\rfloor,m)=\left\lfloor\frac{ax+b}{c}\right\rfloor
min(⌊cax+b⌋,m)=⌊cax+b⌋ 总成立。利用 2.5.布尔计算
、2.4.误差范围
和 2.0.拐弯抹角
,可以知道
f ( a , b , c , n ) = ∑ x = 0 n − 1 ∑ j = 0 m − 1 [ j + 1 ≤ ⌊ a x + b c ⌋ ] = ∑ x = 0 n − 1 ∑ j = 0 m − 1 [ c j + c ≤ a x + b ] = ∑ j = 0 m − 1 ∑ x = 0 n − 1 [ a x ≥ c j + c − b ] = ∑ j = 0 m − 1 ∑ x = 0 n − 1 [ x ≥ ⌈ c j + c − b a ⌉ ] = ∑ j = 0 m − 1 ∑ x = 0 n − 1 [ x ≥ ⌊ c j + c − b + a − 1 a ⌋ ] \begin{aligned} f(a,b,c,n)&=\sum_{x=0}^{n-1}\sum_{j=0}^{m-1}\left[j+1\le\left\lfloor\frac{ax+b}{c}\right\rfloor\right]\\ &=\sum_{x=0}^{n-1}\sum_{j=0}^{m-1}\left[cj+c\le ax+b\right]\\ &=\sum_{j=0}^{m-1}\sum_{x=0}^{n-1}\left[ax\ge cj+c-b\right]\\ &=\sum_{j=0}^{m-1}\sum_{x=0}^{n-1}\left[x\ge\left\lceil\frac{cj+c-b}{a}\right\rceil\right]\\ &=\sum_{j=0}^{m-1}\sum_{x=0}^{n-1}\left[x\ge\left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor\right] \end{aligned} f(a,b,c,n)=x=0∑n−1j=0∑m−1[j+1≤⌊cax+b⌋]=x=0∑n−1j=0∑m−1[cj+c≤ax+b]=j=0∑m−1x=0∑n−1[ax≥cj+c−b]=j=0∑m−1x=0∑n−1[x≥⌈acj+c−b⌉]=j=0∑m−1x=0∑n−1[x≥⌊acj+c−b+a−1⌋]
这很难计算。我们利用容斥,对于每一个
j
j
j,计算有多少个
x
x
x 是不满足此条件的。然后就可以利用 2.5.布尔计算
了。于是乎……
f ( a , b , c , n ) = ∑ j = 0 m − 1 ∑ x = 0 n − 1 [ x ≥ ⌊ c j + c − b + a − 1 a ⌋ ] = n m − ∑ j = 0 m − 1 ∑ x = 0 n − 1 [ x < ⌊ c j + c − b + a − 1 a ⌋ ] = n m − ∑ j = 0 m − 1 min ( n , ⌊ c j + c − b + a − 1 a ⌋ ) \begin{aligned} f(a,b,c,n)&=\sum_{j=0}^{m-1}\sum_{x=0}^{n-1}\left[x\ge\left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor\right]\\ &=nm-\sum_{j=0}^{m-1}\sum_{x=0}^{n-1}\left[x<\left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor\right]\\ &=nm-\sum_{j=0}^{m-1}\min\left(n,\left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor\right) \end{aligned} f(a,b,c,n)=j=0∑m−1x=0∑n−1[x≥⌊acj+c−b+a−1⌋]=nm−j=0∑m−1x=0∑n−1[x<⌊acj+c−b+a−1⌋]=nm−j=0∑m−1min(n,⌊acj+c−b+a−1⌋)
显然,在
j
j
j 最大时(即
j
j
j 取
m
−
1
m-1
m−1 时),其最大值
max
(
⌊
c
j
+
c
−
b
+
a
−
1
a
⌋
)
≤
⌊
n
a
−
1
a
⌋
=
n
−
1
\max\left(\left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor\right)\le\left\lfloor\frac{na-1}{a}\right\rfloor=n-1
max(⌊acj+c−b+a−1⌋)≤⌊ana−1⌋=n−1
即: ⌊ c j + c − b + a − 1 a ⌋ < n \left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor<n ⌊acj+c−b+a−1⌋<n 恒成立(该不等式在以后的叙述中也十分有用)。
所以
f ( a , b , c , n ) = n m − ∑ j = 0 m − 1 ⌊ c j + c − b + a − 1 a ⌋ = n m − f ( c , c − b + a − 1 , a , m ) \begin{aligned} f(a,b,c,n)&=nm-\sum_{j=0}^{m-1}\left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor\\ &=nm-f(c,c-b+a-1,a,m) \end{aligned} f(a,b,c,n)=nm−j=0∑m−1⌊acj+c−b+a−1⌋=nm−f(c,c−b+a−1,a,m)
3.1.3.总结
请注意公差
a
a
a 与除数
c
c
c 的变化。在 3.1.1.情况一
中,
a
′
=
a
m
o
d
c
a'=a\bmod c
a′=amodc ;在 3.1.2.情况二
中,
a
′
=
c
,
c
′
=
a
a'=c,\;c'=a
a′=c,c′=a 。这跟欧几里得(辗转相除)求最大公约数是相似的。所以得名。
也可以看出,时间复杂度是 O [ log ( a + c ) ] \mathcal O[\log(a+c)] O[log(a+c)] 的。
3.2.求 g g g
写一下,
g
g
g 的定义是
g
(
a
,
b
,
c
,
n
)
=
∑
x
=
0
n
−
1
x
⌊
a
x
+
b
c
⌋
g(a,b,c,n)=\sum_{x=0}^{n-1}x\left\lfloor\frac{ax+b}{c}\right\rfloor
g(a,b,c,n)=x=0∑n−1x⌊cax+b⌋
由于式子的推导在 f f f 中已经进行了很多,一些地方将会沿用 f f f 中的结论。
3.2.1.情况一
当 a ≥ c a\ge c a≥c 或者 b ≥ c b\ge c b≥c 时,
g ( a , b , c , n ) = n ( n − 1 ) ( 2 n − 1 ) 6 ⌊ a c ⌋ + n ( n − 1 ) 2 ⌊ b c ⌋ + g ( a m o d c , b m o d c , c , n ) \begin{aligned} g(a,b,c,n)&=\frac{n(n-1)(2n-1)}{6}\left\lfloor\frac{a}{c}\right\rfloor\\ &+\frac{n(n-1)}{2}\left\lfloor\frac{b}{c}\right\rfloor\\ &+g(a\bmod c,b\bmod c,c,n) \end{aligned} g(a,b,c,n)=6n(n−1)(2n−1)⌊ca⌋+2n(n−1)⌊cb⌋+g(amodc,bmodc,c,n)
这里用到了平方和公式。基本方法还是利用 a = c ⌊ a c ⌋ + ( a m o d c ) a=c\left\lfloor\frac{a}{c}\right\rfloor+(a\bmod c) a=c⌊ca⌋+(amodc) 进行替换。
3.2.2.情况二
当 a < c a<c a<c 且 b < c b<c b<c 时,令
m = ⌊ ( n − 1 ) a + b c ⌋ m=\left\lfloor\frac{(n-1)a+b}{c}\right\rfloor m=⌊c(n−1)a+b⌋
则我们可以推出
g ( a , b , c , n ) = ∑ x = 0 n − 1 x ⌊ a x + b c ⌋ = ∑ x = 0 n − 1 ∑ j = 0 m − 1 x [ j + 1 ≤ ⌊ a x + b c ⌋ ] = ∑ x = 0 n − 1 ∑ j = 0 m − 1 x [ x ≥ ⌊ c j + c − b + a − 1 a ⌋ ] = m n ( n − 1 ) 2 − ∑ j = 0 m − 1 ∑ x = 0 n − 1 x [ x < ⌊ c j + c − b + a − 1 a ⌋ ] \begin{aligned} g(a,b,c,n)&=\sum_{x=0}^{n-1}x\left\lfloor\frac{ax+b}{c}\right\rfloor\\ &=\sum_{x=0}^{n-1}\sum_{j=0}^{m-1}x\left[j+1\le\left\lfloor\frac{ax+b}{c}\right\rfloor\right]\\ &=\sum_{x=0}^{n-1}\sum_{j=0}^{m-1}x\left[x\ge\left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor\right]\\ &=m\frac{n(n-1)}{2}-\sum_{j=0}^{m-1}\sum_{x=0}^{n-1}x\left[x<\left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor\right] \end{aligned} g(a,b,c,n)=x=0∑n−1x⌊cax+b⌋=x=0∑n−1j=0∑m−1x[j+1≤⌊cax+b⌋]=x=0∑n−1j=0∑m−1x[x≥⌊acj+c−b+a−1⌋]=m2n(n−1)−j=0∑m−1x=0∑n−1x[x<⌊acj+c−b+a−1⌋]
其中 m n ( n − 1 ) 2 m\frac{n(n-1)}{2} m2n(n−1) 的前身是 ∑ j = 0 m − 1 ∑ x = 0 n − 1 x \sum_{j=0}^{m-1}\sum_{x=0}^{n-1}x ∑j=0m−1∑x=0n−1x 。由于式子太长,我需要将其简化一下。如果设 p = c − b + a − 1 p=c-b+a-1 p=c−b+a−1
那么
g ( a , b , c , n ) = n m ( n − 1 ) 2 − ∑ j = 0 m − 1 ∑ x = 0 ⌊ c j + p a ⌋ − 1 x = n m ( n − 1 ) 2 − ∑ j = 0 m − 1 ⌊ c j + p a ⌋ 2 − ⌊ c j + p a ⌋ 2 = n m ( n − 1 ) − h ( c , p , a , m ) + f ( c , p , a , m ) 2 \begin{aligned} g(a,b,c,n)&=\frac{nm(n-1)}{2}-\sum_{j=0}^{m-1}\sum_{x=0}^{\left\lfloor\frac{cj+p}{a}\right\rfloor-1}x\\ &=\frac{nm(n-1)}{2}-\sum_{j=0}^{m-1}\frac{\left\lfloor\frac{cj+p}{a}\right\rfloor^2-\left\lfloor\frac{cj+p}{a}\right\rfloor}{2}\\ &=\frac{nm(n-1)-h(c,p,a,m)+f(c,p,a,m)}{2} \end{aligned} g(a,b,c,n)=2nm(n−1)−j=0∑m−1x=0∑⌊acj+p⌋−1x=2nm(n−1)−j=0∑m−12⌊acj+p⌋2−⌊acj+p⌋=2nm(n−1)−h(c,p,a,m)+f(c,p,a,m)
3.3.求 h h h
在求 g g g 的时候用到了哟! h ( a , b , c , n ) = ∑ x = 0 n − 1 ⌊ a x + b c ⌋ 2 h(a,b,c,n)=\sum_{x=0}^{n-1}\left\lfloor\frac{ax+b}{c}\right\rfloor^2 h(a,b,c,n)=∑x=0n−1⌊cax+b⌋2 。
3.3.1.情况一
当 a ≥ c a\ge c a≥c 或者 b ≥ c b\ge c b≥c 时,显然有……由于式子太长,我不得不使用一些字符来替换。
令 m a = ⌊ a c ⌋ , r a = a m o d c m_a=\left\lfloor\frac{a}{c}\right\rfloor,\;r_a=a\bmod c ma=⌊ca⌋,ra=amodc 。我并没有对 b b b 进行操作,是为了让式子尽可能的简单。
h ( a , b , c , n ) = ∑ x = 0 n − 1 ( m a x + ⌊ r a x + b c ⌋ ) 2 = ∑ x = 0 n − 1 ( m a 2 x 2 + 2 m a x ⌊ r a x + b c ⌋ + ⌊ r a x + b c ⌋ 2 ) = n ( n − 1 ) ( 2 n − 1 ) 6 m a 2 + 2 m a g ( r a , b , c , n ) + h ( r a , b , c , n ) \begin{aligned} h(a,b,c,n)&=\sum_{x=0}^{n-1}\left(m_a x+\left\lfloor\frac{r_a x+b}{c}\right\rfloor\right)^2\\ &=\sum_{x=0}^{n-1}\left(m_a^2 x^2+2 m_a x \left\lfloor\frac{r_a x+b}{c}\right\rfloor+\left\lfloor\frac{r_a x+b}{c}\right\rfloor^2\right)\\ &=\frac{n(n-1)(2n-1)}{6}m_a^2+2m_ag(r_a,b,c,n)+h(r_a,b,c,n) \end{aligned} h(a,b,c,n)=x=0∑n−1(max+⌊crax+b⌋)2=x=0∑n−1(ma2x2+2max⌊crax+b⌋+⌊crax+b⌋2)=6n(n−1)(2n−1)ma2+2mag(ra,b,c,n)+h(ra,b,c,n)
为了加速,往往不得不将 b b b 同样进行操作。我直接写最后的式子,读者可以自行推导一下。
h ( a , b , c , n ) = n ( n − 1 ) ( 2 n − 1 ) 6 m a 2 + n m b 2 + h ( r a , r b , c , n ) + n ( n − 1 ) m a m b + 2 m a g ( r a , r b , c , n ) + 2 m b f ( r a , r b , c , n ) \begin{aligned} h(a,b,c,n)=&\frac{n(n-1)(2n-1)}{6}m_a^2\\ &+nm_b^2+h(r_a,r_b,c,n)\\ &+n(n-1)m_a m_b\\ &+2m_a g(r_a,r_b,c,n)\\ &+2 m_b f(r_a,r_b,c,n) \end{aligned} h(a,b,c,n)=6n(n−1)(2n−1)ma2+nmb2+h(ra,rb,c,n)+n(n−1)mamb+2mag(ra,rb,c,n)+2mbf(ra,rb,c,n)
3.3.2.情况二
当
a
<
c
a<c
a<c 并且
b
<
c
b<c
b<c 时,仍然是
m
=
⌊
(
n
−
1
)
a
+
b
c
⌋
m=\left\lfloor\frac{(n-1)a+b}{c}\right\rfloor
m=⌊c(n−1)a+b⌋
有一个清奇的思路,利用
n
2
=
n
+
2
∑
x
=
0
n
−
1
x
n^2=n+2\sum_{x=0}^{n-1}x
n2=n+2x=0∑n−1x
将其进行替换。由于式子太长,我不得不使用 p x p_x px 来表示 ⌊ a x + b c ⌋ \left\lfloor\frac{ax+b}{c}\right\rfloor ⌊cax+b⌋ 。
h ( a , b , c , n ) = ∑ x = 0 n − 1 ( p x + 2 ∑ j = 0 p x − 1 j ) = f ( a , b , c , n ) + ∑ x = 0 n − 1 ∑ j = 0 m − 1 [ j + 1 ≤ p x ] 2 j = f ( a , b , c , n ) + ∑ j = 0 m − 1 2 j ∑ x = 0 n − 1 [ x ≥ ⌊ c j + c − b + a − 1 a ⌋ ] = f ( a , b , c , n ) + n m ( m − 1 ) − 2 ∑ j = 0 m − 1 j ⌊ c j + c − b + a − 1 a ⌋ = f ( a , b , c , n ) + n m ( m − 1 ) − 2 g ( c , c − b + a − 1 , a , m ) \begin{aligned} h(a,b,c,n)&=\sum_{x=0}^{n-1}\left(p_x+2\sum_{j=0}^{p_x-1}j\right)\\ &=f(a,b,c,n)+\sum_{x=0}^{n-1}\sum_{j=0}^{m-1}\left[j+1\le p_x\right]2j\\ &=f(a,b,c,n)+\sum_{j=0}^{m-1}2j\sum_{x=0}^{n-1}\left[x\ge\left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor\right]\\ &=f(a,b,c,n)+nm(m-1)-2\sum_{j=0}^{m-1}j\left\lfloor\frac{cj+c-b+a-1}{a}\right\rfloor\\ &=f(a,b,c,n)+nm(m-1)-2g(c,c-b+a-1,a,m) \end{aligned} h(a,b,c,n)=x=0∑n−1(px+2j=0∑px−1j)=f(a,b,c,n)+x=0∑n−1j=0∑m−1[j+1≤px]2j=f(a,b,c,n)+j=0∑m−12jx=0∑n−1[x≥⌊acj+c−b+a−1⌋]=f(a,b,c,n)+nm(m−1)−2j=0∑m−1j⌊acj+c−b+a−1⌋=f(a,b,c,n)+nm(m−1)−2g(c,c−b+a−1,a,m)
3.4.一起求
因为 g g g 和 h h h 会互相使用,而且还需要引用 f f f,非常麻烦。建议一起进行求解,大大降低复杂度。
虽然我们并没有用到 b b b 的正负性,但是,可以发现,如果最初的 b b b 是正数,则递归过程中的所有 b b b 都是正数(毕竟 c − b + a − 1 c-b+a-1 c−b+a−1 在 a < c a<c a<c 且 b < c b<c b<c 情形下出现)。
为了方便代码实现,在此处将三种一起汇总,并且 肆无忌惮地 使用如下符号简化式子:
- m a = ⌊ a c ⌋ , r a = a m o d c m_a=\lfloor\frac{a}{c}\rfloor,\;r_a=a\bmod c ma=⌊ca⌋,ra=amodc 。 m b , r b m_b,r_b mb,rb 的规定同理。
- p = c − b + a − 1 p=c-b+a-1 p=c−b+a−1
- p 1 = n , p 2 = n ( n − 1 ) 2 , p 3 = n ( n − 1 ) ( 2 n − 1 ) 6 p_1=n,\;p_2=\frac{n(n-1)}{2},\;p_3=\frac{n(n-1)(2n-1)}{6} p1=n,p2=2n(n−1),p3=6n(n−1)(2n−1)
3.4.1.情况一
当 a ≥ c a\ge c a≥c 或 b ≥ c b\ge c b≥c 时,
f ( a , b , c , n ) = p 2 m a + p 1 m b + f ( r a , r b , c , n ) f(a,b,c,n)=p_2m_a+p_1m_b+f(r_a,r_b,c,n) f(a,b,c,n)=p2ma+p1mb+f(ra,rb,c,n)
g ( a , b , c , n ) = p 3 m a + p 2 m b + g ( r a , r b , c , n ) g(a,b,c,n)=p_3m_a+p_2m_b+g(r_a,r_b,c,n) g(a,b,c,n)=p3ma+p2mb+g(ra,rb,c,n)
h ( a , b , c , n ) = p 3 m a 2 + 2 p 2 m a m b + p 1 m b 2 + 2 m b f ( r a , r b , c , n ) + 2 m a g ( r a , r b , c , n ) + h ( r a , r b , c , n ) \begin{aligned} &h(a,b,c,n)=p_3m_a^2+2p_2m_a m_b+p_1m_b^2\\ +2 m_b &f(r_a,r_b,c,n)+2m_a g(r_a,r_b,c,n)+h(r_a,r_b,c,n) \end{aligned} +2mbh(a,b,c,n)=p3ma2+2p2mamb+p1mb2f(ra,rb,c,n)+2mag(ra,rb,c,n)+h(ra,rb,c,n)
3.4.2.情况二
当 a < c a<c a<c 并且 b < c b<c b<c 时,令
m = ⌊ ( n − 1 ) a + b c ⌋ m=\left\lfloor\frac{(n-1)a+b}{c}\right\rfloor m=⌊c(n−1)a+b⌋
则有
f ( a , b , c , n ) = n m − f ( c , p , a , m ) f(a,b,c,n)=nm-f(c,p,a,m) f(a,b,c,n)=nm−f(c,p,a,m)
g ( a , b , c , n ) = n m ( n − 1 ) − h ( c , p , a , m ) + f ( c , p , a , m ) 2 g(a,b,c,n)=\frac{nm(n-1)-h(c,p,a,m)+f(c,p,a,m)}{2} g(a,b,c,n)=2nm(n−1)−h(c,p,a,m)+f(c,p,a,m)
h ( a , b , c , n ) = n m ( m − 1 ) − 2 g ( c , p , a , m ) + f ( a , b , c , n ) h(a,b,c,n)=nm(m-1)-2g(c,p,a,m)+f(a,b,c,n) h(a,b,c,n)=nm(m−1)−2g(c,p,a,m)+f(a,b,c,n)
4.代码
struct LL{
long long x;
LL(const long long &num=0):x(num%Mod){}
operator long long(){ return x; }
LL operator * (long long num){
return LL(x*(num%Mod)%Mod);
}
LL operator + (long long num){
return LL((x+num%Mod+Mod)%Mod);
}
LL operator - (long long num){
return LL((x-num%Mod+Mod)%Mod);
}
}; // 注意:LL会强制性取模,所以long long也仍然在被使用
struct PPL{ LL f, g, h; PPL(){ f = g = h = 0; } };
PPL likeGcd(long long a,long long b,long long c,long long n){
if(n == 0) return PPL(); // 没有项数……
long long m = ((n-1)*a+b)/c;
if(a >= c or b >= c){
LL ma = a/c, mb = b/c;
LL yi = LL(n), er = yi*(n-1)*inv2;
LL san = er*(2*n-1)*inv3;
auto res = likeGcd(a%c,b%c,c,n);
res.h = res.h+mb*res.f*2ll+ma*res.g*2ll;
res.h = res.h+san*ma*ma+er*ma*mb*2ll+yi*mb*mb;
res.f = res.f+er*ma+yi*mb;
res.g = res.g+san*ma+er*mb;
return res;
}
else{
if(a == 0) return PPL();
auto last = likeGcd(c,c-b+a-1,a,m);
PPL now; LL cs = LL(n)*m;
now.f = cs-last.f;
now.g = (cs*(n-1)-last.h+last.f)*inv2;
now.h = cs*(m-1)-last.g*2ll+now.f;
return now;
}
}
5.进阶
5.1.讲解
传送门 to ZZQ’blog:更通用的,求
∑
x
=
0
n
x
p
⋅
⌊
a
x
+
b
c
⌋
q
\sum_{x=0}^{n}x^{p}\cdot\left\lfloor\frac{ax+b}{c}\right\rfloor^q
x=0∑nxp⋅⌊cax+b⌋q
记其为 f ( p , q , a , b , c , n ) f(p,q,a,b,c,n) f(p,q,a,b,c,n) 。 a ≥ c ∨ b ≥ c a\ge c\vee b\ge c a≥c∨b≥c 时,需要利用二项式展开化简,挺麻烦的。下面假设 a < c ∧ b < c a<c\wedge b<c a<c∧b<c 。注意:虽然 b b b 并不参与复杂度计算,但是为了下面的式子成立,必须要每一项都大于零(否则 ∑ x p \sum x^p ∑xp 会出问题)。我就这样 W A \rm WA WA 穿了,顶你个肺啊!
如果仍然要用 j ≤ ⌊ a x + b c ⌋ j\le\lfloor\frac{ax+b}{c}\rfloor j≤⌊cax+b⌋ 来化简,那么 j j j 上面所附加的权值是什么呢?好像并没有一个很 t r i c k y \rm tricky tricky 的方案,不如就平凡地令其为 j q − ( j − 1 ) q j^q-(j-1)^q jq−(j−1)q 吧!
仍然记 m = ⌊ a n + b c ⌋ m=\lfloor{an+b\over c}\rfloor m=⌊can+b⌋,即最大的一项。
f ( p , q , a , b , c , n ) = ∑ x = 0 n x p ∑ j = 1 m [ j ≤ ⌊ a x + b c ⌋ ] [ j q − ( j − 1 ) q ] = ∑ j = 1 m [ j q − ( j − 1 ) q ] ∑ x = 1 n x p [ c j − b − 1 < a x ] = ∑ j = 0 m − 1 [ ( j + 1 ) q − j q ] ( ∑ x = 0 n x p − ∑ x = 0 ⌊ c j + c − b − 1 a ⌋ x p ) f(p,q,a,b,c,n) =\sum_{x=0}^{n}x^p\;\sum_{j=1}^{m}\left[j\le \left\lfloor\frac{ax+b}{c}\right\rfloor\right]\;[j^q-(j-1)^q]\\ =\sum_{j=1}^{m}[j^q-(j-1)^q]\sum_{x=1}^{n}x^p\left[cj-b-1<ax\right]\\ =\sum_{j=0}^{m-1}[(j+1)^q-j^q]\left(\sum_{x=0}^{n}x^p-\sum_{x=0}^{\lfloor{cj+c-b-1\over a}\rfloor}x^p\right) f(p,q,a,b,c,n)=x=0∑nxpj=1∑m[j≤⌊cax+b⌋][jq−(j−1)q]=j=1∑m[jq−(j−1)q]x=1∑nxp[cj−b−1<ax]=j=0∑m−1[(j+1)q−jq]⎝⎛x=0∑nxp−x=0∑⌊acj+c−b−1⌋xp⎠⎞
题外话:发现最麻烦的是 x x x 的范围到底 要不要包含零?以及 0 0 0^0 00 该算什么?因为这个考虑,我最终又把 j j j 的范围改成了从零开始。
第一项, j , x j,x j,x 是独立的,可以分开求和然后相乘。第二项,好像比较复杂,可是回想一下,我们既然是要递归,那就要把它跟 ⌊ c j + c − b − 1 a ⌋ \lfloor{cj+c-b-1\over a}\rfloor ⌊acj+c−b−1⌋,也就是 x x x 的取值范围,构建关联。这很简单——事先解出 ∑ x ≤ n x p \sum_{x\le n}x^p ∑x≤nxp 关于 n n n 的多项式,将每一项代入,都是递归子问题。
对于左边的 ( j + 1 ) q (j+1)^q (j+1)q 和 j q j^q jq 两项,要注意了,必须二项式展开,变为 j j j 的多项式,才能递归。否则,我们要递归 ( j + 1 ) q (j+1)^q (j+1)q 则必须是 ⌊ c ( j + 1 ) − b − 1 a ⌋ \lfloor\frac{c(j+1)-b-1}{a}\rfloor ⌊ac(j+1)−b−1⌋ 的 p ′ p' p′ 次幂,那就是 f ( q , p ′ , c , − b − 1 , a , m − 1 ) f(q,p',c,-b-1,a,m-1) f(q,p′,c,−b−1,a,m−1) 的事儿,递归两次的话,复杂度就爆炸了!
所以 f ( p , q , a , b , c , n ) f(p,q,a,b,c,n) f(p,q,a,b,c,n) 要用到 f ( q ′ , p ′ , c , c − b − 1 , a , m − 1 ) ( q ′ < q , p ′ ≤ p + 1 ) f(q',p',c,c-b-1,a,m-1)\;(q'<q,\;p'\le p+1) f(q′,p′,c,c−b−1,a,m−1)(q′<q,p′≤p+1) 。那么我们可以对于 a , b , c , n a,b,c,n a,b,c,n 求出所有 p + q ≤ v 0 p+q\le v_0 p+q≤v0 的值。复杂度则为 O ( v 0 4 log ( a + c ) ) \mathcal O(v_0^4\log(a+c)) O(v04log(a+c)) 。
对于预处理 ∑ x p \sum x^p ∑xp,我觉得利用这个计算方法还挺不错的,当然你可以有更好的想法。
5.2.实现
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;
typedef long long int_;
# define rep(i,a,b) for(int i=(a); i<=(b); ++i)
# define drep(i,a,b) for(int i=(a); i>=(b); --i)
inline int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0'||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
const int Mod = 1e9+7;
inline int qkpow(int_ b,int q){
int a = 1; b %= Mod;
for(; q; q>>=1,b=b*b%Mod)
if(q&1) a = a*b%Mod;
return a;
}
const int MaxN = 50;
namespace Math{
int c[MaxN][MaxN], inv[MaxN];
int poly[MaxN][MaxN+1];
void import(int n){
rep(i,0,n) rep(j,c[i][0]=1,i)
c[i][j] = (c[i-1][j]+c[i-1][j-1])%Mod;
poly[0][0] = poly[0][1] = 1; // \sum_{x} x^0 = n+1
for(int k=inv[1]=1; k<=n; ++k){
inv[k+1] = (0ll+Mod-Mod/(k+1))
*inv[Mod%(k+1)]%Mod;
rep(j,0,k+1) poly[k][j] = c[k+1][j];
rep(j,0,k-1) rep(i,0,j+1)
poly[k][i] = (poly[k][i]+Mod-1ll*
poly[j][i]*c[k+1][j]%Mod)%Mod;
rep(j,0,k+1) poly[k][j] = 1ll*
poly[k][j]*inv[k+1]%Mod;
}
}
int valueAt(int id,int x){
int res = 0, v = 1;
for(int i=0; i<=id+1; ++i,v=1ll*v*x%Mod)
res = (res+1ll*v*poly[id][i])%Mod;
return res;
}
}
int res[MaxN][MaxN], tmp[MaxN][MaxN];
void likeGcd(int v0,int a,int b,int c,int_ n){
if(a == 0 || n == 0){
b /= c; // constant
rep(p,0,v0) rep(q,0,v0-p)
res[p][q] = 1ll*qkpow(b,q)
*Math::valueAt(p,n)%Mod;
return ;
}
if(b >= c){ // don't ignore this!!!
likeGcd(v0,a,b%c,c,n);
rep(p,0,v0) memset(tmp[p]+1,0,v0<<2);
rep(p,0,v0) rep(q,1,v0-p)
for(int i=0,x=1; i<=q; ++i){
tmp[p][q] = (tmp[p][q]+1ll*x*
Math::c[q][i]%Mod*res[p][q-i])%Mod;
x = 1ll*x*(b/c)%Mod; // attached value
}
rep(p,0,v0) tmp[p][0] = Math::valueAt(p,n);
swap(res,tmp); return ;
}
if(a >= c){
likeGcd(v0,a%c,b,c,n);
rep(p,0,v0) memset(tmp[p]+1,0,v0<<2);
rep(p,0,v0) rep(q,1,v0-p)
for(int i=0,x=1; i<=q; ++i){
tmp[p][q] = (tmp[p][q]+1ll*x*
Math::c[q][i]%Mod*res[p+i][q-i])%Mod;
x = 1ll*x*(a/c)%Mod; // attached value
}
rep(p,0,v0) tmp[p][0] = Math::valueAt(p,n);
swap(res,tmp); return ;
}
int_ m = (1ll*a*n+b)/c; // max one
if(c*m > 1ll*a*n+b) -- m;
likeGcd(v0,c,c-b-1,a,m-1);
rep(p,0,v0) rep(q,0,v0-p){
tmp[p][q] = Math::valueAt(p,n);
tmp[p][q] = 1ll*tmp[p][q]*qkpow(m,q)%Mod;
rep(j,0,q-1) rep(i,0,p+1){
int wxk = 1ll*Math::c[q][j]
*Math::poly[p][i]%Mod*res[j][i]%Mod;
tmp[p][q] = (tmp[p][q]+Mod-wxk)%Mod;
}
}
swap(res,tmp); return ;
}
6.例题
答案?什么答案?例题的参考答案?读者自证不难啊!
6.1.模板题
传送门 to luogu:就用上面的模板代码就可以了。
6.2.进阶版
传送门 to LOJ:板题。