这个东西看起来好恐怖啊QAQ.jpg搞了几天,QWQ
其实类欧几里得算法,就是和欧几里得算法类似(欧几里得算法就是gcd那一堆啦),但是其实只有时间复杂度的证明是和gcd一样的,其它的都完全不同,emmmm。
先前置两道例题:【luoug-T36097 整点与质数】【[COCI2009-2010#1] ALADIN
】【讲解by hdxrie】
其实这个就是一个十分简单的类欧算法的应用
以前做到的时候还不知道,现在学了才知道,QAQ
我们可以从一个简单的式子来入门,并对其套路有一定的了解。
T ≤ 1 0 5 T\leq 10^5 T≤105组询问,每组对于给定的 n ≤ 1 0 9 n\leq 10^9 n≤109求下面式子在 m o d 998244353 \rm mod\ 998244353 mod 998244353意义下的值 ( a , b ≥ 0 , c > 0 ) (a,b\geq 0,c>0) (a,b≥0,c>0):
∑ i = 0 n ⌊ a i + b c ⌋ \sum_{i=0}^n\left\lfloor\frac{ai+b}{c}\right\rfloor i=0∑n⌊cai+b⌋
其实前面的 ⌊ i p q ⌋ \left\lfloor\frac{ip}{q}\right\rfloor ⌊qip⌋就是这个式子的简化版, b = 0 b=0 b=0。
显然这个不能直接 O ( n ) O(n) O(n)算,或者除法分块,所以我们要另寻它路。
首先我们可以分成两步考虑:
- a ≥ c a\geq c a≥c或者 b ≥ c b\geq c b≥c时
此时,我们显然可以将原式写成:
∑ i = 0 n ( ⌊ a c ⌋ i + ⌊ b c ⌋ + ⌊ ( a % c ) i + ( b % c ) c ⌋ ) \sum_{i=0}^n\left(\left\lfloor\frac{a}{c}\right\rfloor i+\left\lfloor\frac{b}{c}\right\rfloor+\left\lfloor\frac{(a\%c)i+(b\%c)}{c}\right\rfloor\right) i=0∑n(⌊ca⌋i+⌊cb⌋+⌊c(a%c)i+(b%c)⌋)
将其拆开可以得到:
⌊ a c ⌋ ∑ i = 0 n i + ∑ i = 0 n ⌊ b c ⌋ + ∑ i = 0 n ⌊ ( a % c ) i + ( b % c ) c ⌋ \left\lfloor\frac{a}{c}\right\rfloor\sum_{i=0}^ni+\sum_{i=0}^n\left\lfloor\frac{b}{c}\right\rfloor+\sum_{i=0}^n\left\lfloor\frac{(a\%c)i+(b\%c)}{c}\right\rfloor ⌊ca⌋i=0∑ni+i=0∑n⌊cb⌋+i=0∑n⌊c(a%c)i+(b%c)⌋
前面两个可以用公式 O ( 1 ) O(1) O(1)的求,而后面那个又是一个类似的子问题,递归求解即可。
所以我们令 f ( a , b , c , n ) = ∑ i = 0 n ⌊ a i + b c ⌋ f(a,b,c,n)=\sum_{i=0}^n\left\lfloor\frac{ai+b}{c}\right\rfloor f(a,b,c,n)=∑i=0n⌊cai+b⌋,那么原式可以写成:
f ( a , b , c , n ) = ⌊ a c ⌋ n × ( n + 1 ) 2 + ( n + 1 ) ⌊ b c ⌋ + f ( a % c , b % c , c , n ) f(a,b,c,n)=\left\lfloor\frac{a}{c}\right\rfloor\frac{n\times (n+1)}{2}+(n+1)\left\lfloor\frac{b}{c}\right\rfloor+f(a\%c,b\%c,c,n) f(a,b,c,n)=⌊ca⌋2n×(n+1)+(n+1)⌊cb⌋+f(a%c,b%c,c,n)
此时我们就把问题从 a ≥ c , b ≥ c a\geq c,b\geq c a≥c,b≥c转换 a , b < c a,b<c a,b<c的情况了。
- 那么显然另外一种情况就是 a < c a<c a<c且 b < c b<c b<c的时候了。
其实,如果看了 h d x r i e \rm hdxrie hdxrie的关于 [ C O C I 2010 ] A L A D I N \rm [COCI2010]ALADIN [COCI2010]ALADIN的那个题的讲解,这个也就是相当于求一条直线下整点个数,具体讲解可以看这篇论文【洪华敦-类欧几里得算法】。
那么我们可以枚举整点的坐标,原式就可以转化成(这里 m = ⌊ a n + b c ⌋ − 1 m=\lfloor\frac{an+b}{c}\rfloor-1 m=⌊can+b⌋−1):
f ( a , b , c , n ) = ∑ i = 0 n ∑ j = 1 m + 1 [ j ⩽ ⌊ a i + b c ⌋ ] f(a,b,c,n)=\sum_{i=0}^n\sum_{j=1}^{m+1}[j\leqslant \left\lfloor\frac{ai+b}{c}\right\rfloor] f(a,b,c,n)=i=0∑nj=1∑m+1[j⩽⌊cai+b⌋]
这里 [ a = 1 ] [a=1] [a=1]这种是逻辑判断符,如果里面语句为真,那么值为1,否则为0。
其实这里就是相当于一条 y = a x + b c y=\frac{ax+b}{c} y=cax+b的直线,所以我们枚举 i i i就是枚举的 x x x, j j j就是 y y y,如果 j j j小于等于的话 ( i , j ) (i,j) (i,j)就是在这个直线下的整点。
然后我们先交换枚举顺序可以得到:
由于 a ⩽ ⌊ b ⌋ a\leqslant \lfloor b\rfloor a⩽⌊b⌋时也满足 a ⩽ b a\leqslant b a⩽b,所以变换时可以把向下取整符号去掉。
f ( a , b , c , n ) = ∑ j = 1 m + 1 ∑ i = 0 n [ j ⩽ ⌊ a i + b c ⌋ ] = ∑ j = 0 m ∑ i = 0 n [ j + 1 ⩽ ⌊ a i + b c ⌋ ] = ∑ j = 0 m ∑ i = 0 n [ j + 1 ⩽ a i + b c ] = ∑ j = 0 m ∑ i = 0 n [ j c + c ⩽ a i + b ] = ∑ j = 0 m ∑ i = 0 n [ a i ⩾ j c + c − b ] = ∑ j = 0 m ∑ i = 0 n [ a i > j c + c − b − 1 ] = ∑ j = 0 m ∑ i = 0 n [ i > ⌊ j c + c − b − 1 a ⌋ ] \begin{aligned} f(a,b,c,n)=&\sum_{j=1}^{m+1}\sum_{i=0}^n[j\leqslant \left\lfloor\frac{ai+b}{c}\right\rfloor] \\ =&\sum_{j=0}^{m}\sum_{i=0}^n[j+1\leqslant \left\lfloor\frac{ai+b}{c}\right\rfloor] \\ =&\sum_{j=0}^{m}\sum_{i=0}^n[j+1\leqslant \frac{ai+b}{c}] \\ =&\sum_{j=0}^{m}\sum_{i=0}^n[jc+c\leqslant ai+b] \\ =&\sum_{j=0}^{m}\sum_{i=0}^n[ai\geqslant jc+c-b] \\ =&\sum_{j=0}^{m}\sum_{i=0}^n[ai>jc+c-b-1] \\ =&\sum_{j=0}^{m}\sum_{i=0}^n[i>\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor] \end{aligned} f(a,b,c,n)=======j=1∑m+1i=0∑n[j⩽⌊cai+b⌋]j=0∑mi=0∑n[j+1⩽⌊cai+b⌋]j=0∑mi=0∑n[j+1⩽cai+b]j=0∑mi=0∑n[jc+c⩽ai+b]j=0∑mi=0∑n[ai⩾jc+c−b]j=0∑mi=0∑n[ai>jc+c−b−1]j=0∑mi=0∑n[i>⌊ajc+c−b−1⌋]
由于在 i ∈ [ 0 , n ] i\in[0,n] i∈[0,n]中的 i > ⌊ j c + c − b − 1 a ⌋ i>\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor i>⌊ajc+c−b−1⌋的只有 ⌊ j c + c − b − 1 a ⌋ ∼ n \left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\sim n ⌊ajc+c−b−1⌋∼n,所以进而化简得:
f ( a , b , c , n ) = ∑ j = 0 m ( n − ⌊ j c + c − b − 1 a ⌋ ) = ∑ j = 0 m n − ∑ j = 0 m ⌊ j c + c − b − 1 a ⌋ = n × ( m + 1 ) − f ( c , c − b − 1 , a , m ) \begin{aligned} f(a,b,c,n)=&\sum_{j=0}^{m}\left(n-\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\right) \\ =&\sum_{j=0}^{m}n-\sum_{j=0}^{m}\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor \\ =&\ n\times (m+1)-f(c,c-b-1,a,m) \end{aligned} f(a,b,c,n)===j=0∑m(n−⌊ajc+c−b−1⌋)j=0∑mn−j=0∑m⌊ajc+c−b−1⌋ n×(m+1)−f(c,c−b−1,a,m)
那么这样又可以将 f ( a , b , c , n ) ⇒ f ( c , c − b − 1 , a , ⌊ a n + b c ⌋ − 1 ) f(a,b,c,n)\Rightarrow f(c,c-b-1,a,\left\lfloor\frac{an+b}{c}\right\rfloor-1) f(a,b,c,n)⇒f(c,c−b−1,a,⌊can+b⌋−1),又将问题变小了。
那么边界就是当:
- n = 0 n=0 n=0时,直接返回 ⌊ b c ⌋ \lfloor\frac{b}{c}\rfloor ⌊cb⌋
- a = 0 a=0 a=0时,就是 ( n + 1 ) × ⌊ b c ⌋ (n+1)\times \lfloor\frac{b}{c}\rfloor (n+1)×⌊cb⌋
f总结
f ( a , b , c , n ) = { ⌊ b c ⌋ n = 0 ( n + 1 ) × ⌊ b c ⌋ a = 0 ⌊ a c ⌋ n × ( n + 1 ) 2 + ( n + 1 ) ⌊ b c ⌋ + f ( a % c , b % c , c , n ) a ⩾ c o r b ⩾ c n × ⌊ a n + b c ⌋ − f ( c , c − b − 1 , a , m ) a < c a n d b < c f(a,b,c,n)=\begin{cases}\lfloor\frac{b}{c}\rfloor&n=0\\ (n+1)\times \lfloor\frac{b}{c}\rfloor&a=0\\ \left\lfloor\frac{a}{c}\right\rfloor\frac{n\times (n+1)}{2}+(n+1)\left\lfloor\frac{b}{c}\right\rfloor+f(a\%c,b\%c,c,n)&a\geqslant c\ or\ b\geqslant c\\ n\times \left\lfloor\frac{an+b}{c}\right\rfloor-f(c,c-b-1,a,m)&a<c\ and\ b<c\end{cases} f(a,b,c,n)=⎩⎪⎪⎪⎨⎪⎪⎪⎧⌊cb⌋(n+1)×⌊cb⌋⌊ca⌋2n×(n+1)+(n+1)⌊cb⌋+f(a%c,b%c,c,n)n×⌊can+b⌋−f(c,c−b−1,a,m)n=0a=0a⩾c or b⩾ca<c and b<c
这时就已经可以写出一份十分简单的递归的代码了:
int S1(int n){return n*(n+1)/2;}
int f(int a,int b,int c,int n){
if(!n) return b/c;
if(!a) return (n+1)*(b/c);
if(a>=c||b>=c)return S1(n)*(a/c)+n*(b/c)+f(a%c,b%c,c,n);
return n*((a*n+b)/c)-f(c,c-b-1,a,(a*n+b)/c-1);
}
关于复杂度,首先我们看 a ≥ c , b ≥ c a\geq c,b\geq c a≥c,b≥c的时候只需 O ( 1 ) O(1) O(1)就转移到了 a < c , b < c a<c,b<c a<c,b<c的情况了,而这时 f ( a , b , c , n ) ⇒ f ( c , c − b − 1 , a , ⌊ a n + b c ⌋ − 1 ) f(a,b,c,n)\Rightarrow f(c,c-b-1,a,\left\lfloor\frac{an+b}{c}\right\rfloor-1) f(a,b,c,n)⇒f(c,c−b−1,a,⌊can+b⌋−1)这个就十分类似于欧几里得算法的更相减损术,直到 a = 0 a=0 a=0或 n = 0 n=0 n=0时就停止了,那么复杂度就类似于欧几里得算法,是 O ( l o g n ) O(logn) O(logn)的。
有了初步的了解,我们就可以看看稍微难一点的:
同样的条件,再求下面两个式子的值:
∑ i = 0 n ( ⌊ a i + b c ⌋ ) 2 \sum_{i=0}^n\left(\left\lfloor\frac{ai+b}{c}\right\rfloor\right)^2 i=0∑n(⌊cai+b⌋)2
和
∑ i = 0 n i ⌊ a i + b c ⌋ \sum_{i=0}^ni\left\lfloor\frac{ai+b}{c}\right\rfloor i=0∑ni⌊cai+b⌋
之所以放在一起说,是因为这两个在求取的过程中会有联系,而且还要用到前面的 f f f。
首先我们令 h ( a , b , c , n ) = ∑ i = 0 n ( ⌊ a i + b c ⌋ ) 2 , g ( a , b , c , n ) = ∑ i = 0 n i ⌊ a i + b c ⌋ h(a,b,c,n)=\sum_{i=0}^n\left(\left\lfloor\frac{ai+b}{c}\right\rfloor\right)^2,g(a,b,c,n)=\sum_{i=0}^ni\left\lfloor\frac{ai+b}{c}\right\rfloor h(a,b,c,n)=∑i=0n(⌊cai+b⌋)2,g(a,b,c,n)=∑i=0ni⌊cai+b⌋
那么我们先来看 h h h的求法,和 f f f类似(其实类欧的套路都差不多是这样),我们分两块考虑:
- 当 a ≥ c a\geq c a≥c或者 b ≥ c b\geq c b≥c时:
显然同理有:
h ( a , b , c , n ) = ∑ i = 0 n ( ⌊ a c ⌋ i + ⌊ b c ⌋ + ⌊ ( a % c ) i + ( b % c ) c ⌋ ) 2 h(a,b,c,n)=\sum_{i=0}^n\left(\left\lfloor\frac{a}{c}\right\rfloor i+\left\lfloor\frac{b}{c}\right\rfloor+\left\lfloor\frac{(a\%c)i+(b\%c)}{c}\right\rfloor\right)^2 h(a,b,c,n)=i=0∑n(⌊ca⌋i+⌊cb⌋+⌊c(a%c)i+(b%c)⌋)2
我们把那个恐怖的括号打开,可以得到(
(
a
+
b
+
c
)
2
=
a
2
+
b
2
+
c
2
+
2
a
b
+
2
b
c
+
2
a
c
(a+b+c)^2=a^2+b^2+c^2+2ab+2bc+2ac
(a+b+c)2=a2+b2+c2+2ab+2bc+2ac):
h ( a , b , c , n ) = ∑ i = 0 n ( ⌊ a c ⌋ i ) 2 + ∑ i = 0 n ( ⌊ b c ⌋ ) 2 + ∑ i = 0 n ( ⌊ ( a % c ) i + ( b % c ) c ⌋ ) 2 + ∑ i = 0 n 2 ⋅ ⌊ a c ⌋ i ⋅ ⌊ b c ⌋ + ∑ i = 0 n 2 ⋅ ⌊ b c ⌋ ⋅ ⌊ ( a % c ) i + ( b % c ) c ⌋ + ∑ i = 0 n 2 ⋅ ⌊ a c ⌋ i ⋅ ⌊ ( a % c ) i + ( b % c ) c ⌋ h(a,b,c,n)=\sum_{i=0}^n\left(\left\lfloor\frac{a}{c}\right\rfloor i\right)^2+\sum_{i=0}^{n}\left(\left\lfloor\frac{b}{c}\right\rfloor\right)^2+\sum_{i=0}^n\left(\left\lfloor\frac{(a\%c)i+(b\%c)}{c}\right\rfloor\right)^2 \\ +\sum_{i=0}^n2\cdot \left\lfloor\frac{a}{c}\right\rfloor i\cdot \left\lfloor\frac{b}{c}\right\rfloor+\sum_{i=0}^n2\cdot\left\lfloor\frac{b}{c}\right\rfloor\cdot\left\lfloor\frac{(a\%c)i+(b\%c)}{c}\right\rfloor+\sum_{i=0}^n2\cdot\left\lfloor\frac{a}{c}\right\rfloor i\cdot\left\lfloor\frac{(a\%c)i+(b\%c)}{c}\right\rfloor h(a,b,c,n)=i=0∑n(⌊ca⌋i)2+i=0∑n(⌊cb⌋)2+i=0∑n(⌊c(a%c)i+(b%c)⌋)2+i=0∑n2⋅⌊ca⌋i⋅⌊cb⌋+i=0∑n2⋅⌊cb⌋⋅⌊c(a%c)i+(b%c)⌋+i=0∑n2⋅⌊ca⌋i⋅⌊c(a%c)i+(b%c)⌋
我们把这一大坨,整理化简一下,可以得到:
由于 ∑ i = 0 n i 2 = n × ( n + 1 ) × ( 2 n + 1 ) 6 \sum_{i=0}^ni^2=\frac{n\times (n+1)\times(2n+1)}{6} ∑i=0ni2=6n×(n+1)×(2n+1), ∑ i = 0 n i = n × ( n + 1 ) 2 \sum_{i=0}^ni=\frac{n\times(n+1)}{2} ∑i=0ni=2n×(n+1)
h ( a , b , c , n ) = ( ⌊ a c ⌋ ) 2 n × ( n + 1 ) × ( 2 n + 1 ) 6 + ( n + 1 ) × ( ⌊ b c ⌋ ) 2 + h ( a % c , b % c , c , n ) + 2 ⋅ ⌊ a c ⌋ ⋅ ⌊ b c ⌋ ⋅ n × ( n + 1 ) 2 + 2 ⋅ ⌊ b c ⌋ ⋅ f ( a % c , b % c , c , n ) + 2 ⋅ ⌊ a c ⌋ ⋅ g ( a % c , b % c , c , n ) h(a,b,c,n)=\left(\left\lfloor\frac{a}{c}\right\rfloor\right)^2\frac{n\times(n+1)\times(2n+1)}{6}+(n+1)\times\left(\left\lfloor\frac{b}{c}\right\rfloor\right)^2+h(a\%c,b\%c,c,n) \\ +2\cdot \left\lfloor\frac{a}{c}\right\rfloor\cdot \left\lfloor\frac{b}{c}\right\rfloor\cdot\frac{n\times(n+1)}{2}+2\cdot\left\lfloor\frac{b}{c}\right\rfloor\cdot f(a\%c,b\%c,c,n)+2\cdot\left\lfloor\frac{a}{c}\right\rfloor\cdot g(a\%c,b\%c,c,n) h(a,b,c,n)=(⌊ca⌋)26n×(n+1)×(2n+1)+(n+1)×(⌊cb⌋)2+h(a%c,b%c,c,n)+2⋅⌊ca⌋⋅⌊cb⌋⋅2n×(n+1)+2⋅⌊cb⌋⋅f(a%c,b%c,c,n)+2⋅⌊ca⌋⋅g(a%c,b%c,c,n)
递归处理就可以了(假设我们现在知道 g g g如何计算)。
- 我们继续考虑当 a < c , b < c a<c,b<c a<c,b<c的时候的情况:
通过 f f f的经验,我们照着之前的变换一下看( m m m的意义同前面):
h ( a , b , c , n ) = ∑ i = 0 n ( ∑ j = 1 m + 1 [ j ⩽ ⌊ a i + b c ⌋ ] ) 2 h(a,b,c,n)=\sum_{i=0}^n\left(\sum_{j=1}^{m+1}[j\leqslant \left\lfloor\frac{ai+b}{c}\right\rfloor]\right)^2 h(a,b,c,n)=i=0∑n(j=1∑m+1[j⩽⌊cai+b⌋])2
我们将后面拆成两个式子,然后按照 f f f的方式变换:
h ( a , b , c , n ) = ∑ i = 0 n ( ∑ j = 1 m + 1 [ j ⩽ ⌊ a i + b c ⌋ ] ) × ( ∑ k = 1 m + 1 [ k ⩽ ⌊ a i + b c ⌋ ] ) = ∑ i = 0 n ( ∑ j = 0 m [ j + 1 ⩽ a i + b c ] ) × ( ∑ k = 0 m [ k + 1 ⩽ a i + b c ] ) = ∑ i = 0 n ( ∑ j = 0 m [ j c + c ⩽ a i + b ] ) × ( ∑ k = 0 m [ k c + c ⩽ a i + b ] ) = ∑ i = 0 n ( ∑ j = 0 m [ a i ⩾ j c + c − b ] ) × ( ∑ k = 0 m [ a i ⩾ k c + c − b ] ) = ∑ i = 0 n ( ∑ j = 0 m [ a i > j c + c − b − 1 ] ) × ( ∑ k = 0 m [ a i > k c + c − b − 1 ] ) \begin{aligned} h(a,b,c,n)=&\sum_{i=0}^n\left(\sum_{j=1}^{m+1}[j\leqslant \left\lfloor\frac{ai+b}{c}\right\rfloor]\right)\times \left(\sum_{k=1}^{m+1}[k\leqslant \left\lfloor\frac{ai+b}{c}\right\rfloor]\right) \\ =&\sum_{i=0}^n\left(\sum_{j=0}^{m}[j+1\leqslant \frac{ai+b}{c}]\right)\times \left(\sum_{k=0}^{m}[k+1\leqslant \frac{ai+b}{c}]\right) \\ =&\sum_{i=0}^n\left(\sum_{j=0}^{m}[jc+c\leqslant {ai+b}]\right)\times \left(\sum_{k=0}^{m}[kc+c\leqslant {ai+b}]\right) \\ =&\sum_{i=0}^n\left(\sum_{j=0}^{m}[ai\geqslant jc+c-b]\right)\times \left(\sum_{k=0}^{m}[ai\geqslant {kc+c-b}]\right) \\ =&\sum_{i=0}^n\left(\sum_{j=0}^{m}[ai> jc+c-b-1]\right)\times \left(\sum_{k=0}^{m}[ai> {kc+c-b-1}]\right) \end{aligned} h(a,b,c,n)=====i=0∑n(j=1∑m+1[j⩽⌊cai+b⌋])×(k=1∑m+1[k⩽⌊cai+b⌋])i=0∑n(j=0∑m[j+1⩽cai+b])×(k=0∑m[k+1⩽cai+b])i=0∑n(j=0∑m[jc+c⩽ai+b])×(k=0∑m[kc+c⩽ai+b])i=0∑n(j=0∑m[ai⩾jc+c−b])×(k=0∑m[ai⩾kc+c−b])i=0∑n(j=0∑m[ai>jc+c−b−1])×(k=0∑m[ai>kc+c−b−1])
然后我们同理,交换枚举顺序,可以得到:
h ( a , b , c , n ) = ∑ j = 0 m ∑ k = 0 m ∑ i = 0 n [ a i > max ( j c − b − 1 , k c − b − 1 ) ] = ∑ j = 0 m ∑ k = 0 m ∑ i = 0 n [ i > max ( ⌊ j c + c − b − 1 a ⌋ , ⌊ k c + c − b − 1 a ⌋ ) ] \begin{aligned} h(a,b,c,n)=&\sum_{j=0}^m\sum_{k=0}^m\sum_{i=0}^n[ai>\max(jc-b-1,kc-b-1)] \\ =&\sum_{j=0}^m\sum_{k=0}^m\sum_{i=0}^n[i>\max(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor,\left\lfloor\frac{kc+c-b-1}{a}\right\rfloor)] \end{aligned} h(a,b,c,n)==j=0∑mk=0∑mi=0∑n[ai>max(jc−b−1,kc−b−1)]j=0∑mk=0∑mi=0∑n[i>max(⌊ajc+c−b−1⌋,⌊akc+c−b−1⌋)]
同样, i ∈ [ 0 , n ] i\in[0,n] i∈[0,n]的 i > max ( ⌊ j c + c − b − 1 a ⌋ , ⌊ k c + c − b − 1 a ⌋ ) i>\max(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor,\left\lfloor\frac{kc+c-b-1}{a}\right\rfloor) i>max(⌊ajc+c−b−1⌋,⌊akc+c−b−1⌋)的只有 > max ( ⌊ j c + c − b − 1 a ⌋ , ⌊ k c + c − b − 1 a ⌋ ) ∼ n >\max(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor,\left\lfloor\frac{kc+c-b-1}{a}\right\rfloor)\sim n >max(⌊ajc+c−b−1⌋,⌊akc+c−b−1⌋)∼n这一部分,所以原式还可以写成:
h ( a , b , c , n ) = ∑ j = 0 m ∑ k = 0 m ( n − max ( ⌊ j c + c − b − 1 a ⌋ , ⌊ k c + c − b − 1 a ⌋ ) ) = n ( m + 1 ) 2 − ∑ j = 0 m ∑ k = 0 m max ( ⌊ j c + c − b − 1 a ⌋ , ⌊ k c + c − b − 1 a ⌋ ) \begin{aligned} h(a,b,c,n)=&\sum_{j=0}^{m}\sum_{k=0}^{m}\left(n-\max(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor,\left\lfloor\frac{kc+c-b-1}{a}\right\rfloor)\right) \\ =& n(m+1)^2-\sum_{j=0}^{m}\sum_{k=0}^{m}\max(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor,\left\lfloor\frac{kc+c-b-1}{a}\right\rfloor) \end{aligned} h(a,b,c,n)==j=0∑mk=0∑m(n−max(⌊ajc+c−b−1⌋,⌊akc+c−b−1⌋))n(m+1)2−j=0∑mk=0∑mmax(⌊ajc+c−b−1⌋,⌊akc+c−b−1⌋)
这里的 max \max max不好处理,但是我们可以通过枚举当前这个是 max \max max的贡献,首先 j ⩾ k j\geqslant k j⩾k的部分为:
∑ j = 0 m ( j + 1 ) ⌊ j c + c − b − 1 a ⌋ \sum_{j=0}^{m}(j+1)\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor j=0∑m(j+1)⌊ajc+c−b−1⌋
因为对于每个 j j j,都有 0 ∼ j 0\sim j 0∼j也就是 j + 1 j+1 j+1个 k k k比它小,所以每个的贡献次数是 j + 1 j+1 j+1次。
那么同理对于
j
⩽
k
j\leqslant k
j⩽k的部分就是:
∑
k
=
0
m
(
k
+
1
)
⌊
k
c
+
c
−
b
−
1
a
⌋
\sum_{k=0}^{m}(k+1)\left\lfloor\frac{kc+c-b-1}{a}\right\rfloor
k=0∑m(k+1)⌊akc+c−b−1⌋
但是这两个加起来,会把 j = k j=k j=k的部分多加一次,所以我们减去多加了的这个部分:
∑ j = 0 m ⌊ j c + c − b − 1 a ⌋ \sum_{j=0}^{m}\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor j=0∑m⌊ajc+c−b−1⌋
那么原式就可以变成:
h ( a , b , c , n ) = n ( m + 1 ) 2 − ∑ j = 0 m ∑ k = 0 m max ( ⌊ j c + c − b − 1 a ⌋ , ⌊ k c + c − b − 1 a ⌋ ) = n ( m + 1 ) 2 − ( ∑ j = 0 m ( j + 1 ) ⌊ j c + c − b − 1 a ⌋ + ∑ k = 0 m ( k + 1 ) ⌊ k c + c − b − 1 a ⌋ − ∑ j = 0 m ⌊ j c + c − b − 1 a ⌋ ) = n ( m + 1 ) 2 − ( 2 ⋅ ∑ j = 0 m ( j + 1 ) ⌊ j c + c − b − 1 a ⌋ − ∑ j = 0 m ⌊ j c + c − b − 1 a ⌋ ) \begin{aligned} h(a,b,c,n)=&n(m+1)^2-\sum_{j=0}^{m}\sum_{k=0}^{m}\max(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor,\left\lfloor\frac{kc+c-b-1}{a}\right\rfloor) \\ =&n(m+1)^2-\left(\sum_{j=0}^{m}(j+1)\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor+\sum_{k=0}^{m}(k+1)\left\lfloor\frac{kc+c-b-1}{a}\right\rfloor-\sum_{j=0}^{m}\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\right) \\ =&n(m+1)^2-\left(2\cdot \sum_{j=0}^{m}(j+1)\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor-\sum_{j=0}^{m}\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\right) \end{aligned} h(a,b,c,n)===n(m+1)2−j=0∑mk=0∑mmax(⌊ajc+c−b−1⌋,⌊akc+c−b−1⌋)n(m+1)2−(j=0∑m(j+1)⌊ajc+c−b−1⌋+k=0∑m(k+1)⌊akc+c−b−1⌋−j=0∑m⌊ajc+c−b−1⌋)n(m+1)2−(2⋅j=0∑m(j+1)⌊ajc+c−b−1⌋−j=0∑m⌊ajc+c−b−1⌋)
我们把 ( j + 1 ) (j+1) (j+1)打开,然后整理可以得到:
h ( a , b , c , n ) = n ( m + 1 ) 2 − ( 2 ⋅ ∑ j = 0 m j ⌊ j c + c − b − 1 a ⌋ + 2 ⋅ ∑ j = 0 m ⌊ j c + c − b − 1 a ⌋ − ∑ j = 0 m ⌊ j c + c − b − 1 a ⌋ ) = n ( m + 1 ) 2 − ( 2 ⋅ ∑ j = 0 m j ⌊ j c + c − b − 1 a ⌋ + ∑ j = 0 m ⌊ j c + c − b − 1 a ⌋ ) = n ( m + 1 ) 2 − 2 ⋅ g ( c , c − b − 1 , a , m ) − f ( c , c − b − 1 , a , m ) \begin{aligned} h(a,b,c,n)=&n(m+1)^2-\left(2\cdot \sum_{j=0}^{m}j\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor+2\cdot\sum_{j=0}^{m}\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor-\sum_{j=0}^{m}\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\right) \\ =&n(m+1)^2-\left(2\cdot \sum_{j=0}^{m}j\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor+\sum_{j=0}^{m}\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\right) \\ =&n(m+1)^2-2\cdot g(c,c-b-1,a,m)-f(c,c-b-1,a,m) \end{aligned} h(a,b,c,n)===n(m+1)2−(2⋅j=0∑mj⌊ajc+c−b−1⌋+2⋅j=0∑m⌊ajc+c−b−1⌋−j=0∑m⌊ajc+c−b−1⌋)n(m+1)2−(2⋅j=0∑mj⌊ajc+c−b−1⌋+j=0∑m⌊ajc+c−b−1⌋)n(m+1)2−2⋅g(c,c−b−1,a,m)−f(c,c−b−1,a,m)
那么我们同样可以将其转移到更小的问题上,递归计算即可。
边界同理:
- 当 n = 0 n=0 n=0时,就是 ( b c ) 2 \left(\frac{b}{c}\right)^2 (cb)2
- 当 a = 0 a=0 a=0时,就是 ( n + 1 ) × ( b c ) 2 (n+1)\times \left(\frac{b}{c}\right)^2 (n+1)×(cb)2
h总结
h ( a , b , c , n ) = { ( b c ) 2 n = 0 ( n + 1 ) × ( b c ) 2 a = 0 ( ⌊ a c ⌋ ) 2 n ( n + 1 ) ( 2 n + 1 ) 6 + ( n + 1 ) ( ⌊ b c ⌋ ) 2 + h ( a % c , b % c , c , n ) + 2 ⌊ a c ⌋ ⌊ b c ⌋ n ( n + 1 ) 2 + 2 ⌊ b c ⌋ f ( a % c , b % c , c , n ) + 2 ⌊ a c ⌋ g ( a % c , b % c , c , n ) a ⩾ c o r b ⩾ c n ( m + 1 ) 2 − 2 ⋅ g ( c , c − b − 1 , a , m ) − f ( c , c − b − 1 , a , m ) a < c a n d b < c h(a,b,c,n)=\begin{cases}\left(\frac{b}{c}\right)^2&n=0\\ (n+1)\times \left(\frac{b}{c}\right)^2&a=0\\ \left(\left\lfloor\frac{a}{c}\right\rfloor\right)^2\frac{n(n+1)(2n+1)}{6}+(n+1)\left(\left\lfloor\frac{b}{c}\right\rfloor\right)^2+h(a\%c,b\%c,c,n) +2\left\lfloor\frac{a}{c}\right\rfloor\left\lfloor\frac{b}{c}\right\rfloor\frac{n(n+1)}{2}+2\left\lfloor\frac{b}{c}\right\rfloor f(a\%c,b\%c,c,n)+2\left\lfloor\frac{a}{c}\right\rfloor g(a\%c,b\%c,c,n)&a\geqslant c\ or\ b\geqslant c\\ n(m+1)^2-2\cdot g(c,c-b-1,a,m)-f(c,c-b-1,a,m)&a<c\ and\ b<c\end{cases} h(a,b,c,n)=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧(cb)2(n+1)×(cb)2(⌊ca⌋)26n(n+1)(2n+1)+(n+1)(⌊cb⌋)2+h(a%c,b%c,c,n)+2⌊ca⌋⌊cb⌋2n(n+1)+2⌊cb⌋f(a%c,b%c,c,n)+2⌊ca⌋g(a%c,b%c,c,n)n(m+1)2−2⋅g(c,c−b−1,a,m)−f(c,c−b−1,a,m)n=0a=0a⩾c or b⩾ca<c and b<c
代码同样十分好写,仿照上面的即可,这里就不写了。
接下来只剩下对于 g g g的求法了。
g g g相对 h h h来说就很好变换了,直接跟着套路走:
- 当 a ⩾ c , b ⩾ c a\geqslant c,b\geqslant c a⩾c,b⩾c时:
g ( a , b , c , n ) = ∑ i = 0 n i ⌊ a i + b c ⌋ = ∑ i = 0 n ⌊ a c ⌋ i 2 + ⌊ b c ⌋ i + i ⌊ ( a % c ) i + ( b % c ) c ⌋ = ⌊ a c ⌋ n ( n + 1 ) ( 2 n + 1 ) 6 + ⌊ b c ⌋ n ( n + 1 ) 2 + g ( a % c , b % c , c , n ) \begin{aligned} g(a,b,c,n)=&\sum_{i=0}^ni\left\lfloor\frac{ai+b}{c}\right\rfloor \\ =&\sum_{i=0}^n\left\lfloor\frac{a}{c}\right\rfloor i^2+\left\lfloor\frac{b}{c}\right\rfloor i+i\left\lfloor\frac{(a\%c)i+(b\%c)}{c}\right\rfloor \\ =&\left\lfloor\frac{a}{c}\right\rfloor\frac{n(n+1)(2n+1)}{6}+\left\lfloor\frac{b}{c}\right\rfloor\frac{n(n+1)}{2}+g(a\%c,b\%c,c,n) \end{aligned} g(a,b,c,n)===i=0∑ni⌊cai+b⌋i=0∑n⌊ca⌋i2+⌊cb⌋i+i⌊c(a%c)i+(b%c)⌋⌊ca⌋6n(n+1)(2n+1)+⌊cb⌋2n(n+1)+g(a%c,b%c,c,n)
- 当 a < c , b < c a<c,b<c a<c,b<c
根据套路,我们转换成这个形式:
g ( a , b , c , n ) = ∑ j = 0 m ∑ i = 0 n i [ i > ⌊ j c + c − b − 1 a ⌋ ] = ∑ j = 0 m ∑ i = ⌊ j c + c − b − 1 a ⌋ + 1 n i = ∑ j = 0 m ( ∑ i = 0 n i − ∑ i = 0 ⌊ j c + c − b − 1 a ⌋ i ) = ∑ j = 0 m n ( n + 1 ) 2 − ⌊ j c + c − b − 1 a ⌋ ⋅ ( ⌊ j c + c − b − 1 a ⌋ + 1 ) 2 = 1 2 ( n ( n + 1 ) ( m + 1 ) − ∑ j = 0 m ( ⌊ j c + c − b − 1 a ⌋ ) 2 − ⌊ j c + c − b − 1 a ⌋ ) = 1 2 ( n ( n + 1 ) ( m + 1 ) − h ( c , c − b − 1 , a , m ) − f ( c , c − b − 1 , a , m ) ) \begin{aligned} g(a,b,c,n)=&\sum_{j=0}^{m}\sum_{i=0}^ni[i>\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor] \\ =&\sum_{j=0}^{m}\sum_{i=\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor+1}^ni \\ =&\sum_{j=0}^{m}\left(\sum_{i=0}^ni-\sum_{i=0}^{\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor}i\right) \\ =&\sum_{j=0}^{m}\frac{n(n+1)}{2}-\frac{\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\cdot\left(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor+1\right)}{2} \\ =&\frac{1}{2}\left(n(n+1)(m+1)-\sum_{j=0}^{m}\left(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\right)^2-\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\right) \\ =&\frac{1}{2}\left(n(n+1)(m+1)-h(c,c-b-1,a,m)-f(c,c-b-1,a,m)\right) \end{aligned} g(a,b,c,n)======j=0∑mi=0∑ni[i>⌊ajc+c−b−1⌋]j=0∑mi=⌊ajc+c−b−1⌋+1∑nij=0∑m⎝⎜⎛i=0∑ni−i=0∑⌊ajc+c−b−1⌋i⎠⎟⎞j=0∑m2n(n+1)−2⌊ajc+c−b−1⌋⋅(⌊ajc+c−b−1⌋+1)21(n(n+1)(m+1)−j=0∑m(⌊ajc+c−b−1⌋)2−⌊ajc+c−b−1⌋)21(n(n+1)(m+1)−h(c,c−b−1,a,m)−f(c,c−b−1,a,m))
由此我们可以直接判断后递归计算即可。
边界条件还是一样的:
- 当 n = 0 n=0 n=0时,为 0 0 0。
- 当 a = 0 a=0 a=0时,为 ⌊ b c ⌋ ( n ( n + 1 ) 2 ) \lfloor\frac{b}{c}\rfloor(\frac{n(n+1)}{2}) ⌊cb⌋(2n(n+1))
g总结
g ( a , b , c , n ) = { 0 n = 0 ⌊ b c ⌋ ( n ( n + 1 ) 2 ) a = 0 ⌊ a c ⌋ n ( n + 1 ) ( 2 n + 1 ) 6 + ⌊ b c ⌋ n ( n + 1 ) 2 + g ( a % c , b % c , c , n ) a ⩾ c o r b ⩾ c 1 2 ( n ( n + 1 ) ( m + 1 ) − h ( c , c − b − 1 , a , m ) − f ( c , c − b − 1 , a , m ) ) a < c a n d b < c g(a,b,c,n)=\begin{cases}0&n=0\\ \lfloor\frac{b}{c}\rfloor(\frac{n(n+1)}{2})&a=0\\ \left\lfloor\frac{a}{c}\right\rfloor\frac{n(n+1)(2n+1)}{6}+\left\lfloor\frac{b}{c}\right\rfloor\frac{n(n+1)}{2}+g(a\%c,b\%c,c,n)&a\geqslant c\ or\ b\geqslant c\\ \frac{1}{2}\left(n(n+1)(m+1)-h(c,c-b-1,a,m)-f(c,c-b-1,a,m)\right)& a<c\ and\ b<c\end{cases} g(a,b,c,n)=⎩⎪⎪⎪⎨⎪⎪⎪⎧0⌊cb⌋(2n(n+1))⌊ca⌋6n(n+1)(2n+1)+⌊cb⌋2n(n+1)+g(a%c,b%c,c,n)21(n(n+1)(m+1)−h(c,c−b−1,a,m)−f(c,c−b−1,a,m))n=0a=0a⩾c or b⩾ca<c and b<c
代码同理。
技巧:为了方便求取 g , h g,h g,h,通常我们可以在一个递归里面写,可以降低复杂度,并且写起了也挺简单的。
这个算是个简单的模板了,求的就是上面讲的 f , h , g f,h,g f,h,g函数:
//代码中的h,g的意义对换了一下,懒得改了
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll Mod=998244353;
const ll inv2=499122177,inv6=166374059;
ll S1(ll x){if(x>=Mod)x%=Mod;return (x*(x+1)%Mod)*inv2%Mod;}
ll S2(ll x){if(x>=Mod)x%=Mod;return (x*(x+1)%Mod*(x+x+1)%Mod)*inv6%Mod;}
ll Sqr(ll x){return x*x%Mod;}
struct node{
ll f,g,h;
void clear(){f=g=h=0;}
node(){}
node(ll a,ll b,ll c):f(a),g(b),h(c){}
void out(){printf("%lld %lld %lld\n",f,g,h);}
};
node calc(ll a,ll b,ll c,ll n){
node ans,res;ans.clear();
ll m,t1,t2,s1,s2;
if(!n){ans.f=b/c;ans.g=Sqr(b/c);return ans;}
if(!a){
t1=b/c;
ans.f=(n+1ll)*t1%Mod;
ans.g=(n+1ll)*Sqr(t1)%Mod;
ans.h=S1(n)*t1%Mod;
return ans;
}
if(a>=c||b>=c){
t1=a/c;t2=b/c;
res=calc(a%c,b%c,c,n);
s1=S1(n);s2=S2(n);
ans.f=(((s1*t1%Mod)+(n+1ll)*t2%Mod)%Mod+res.f)%Mod;
ans.g=(((Sqr(t1)*s2%Mod+(n+1ll)*Sqr(t2)%Mod)%Mod)+((t1*t2%Mod)*2ll*s1%Mod+(t1*2ll*res.h%Mod))%Mod+(res.g+t2*2ll*res.f%Mod)%Mod)%Mod;
ans.h=((s2*t1%Mod+s1*t2%Mod)+res.h)%Mod;
return ans;
}
m=(n*a+b)/c-1;
res=calc(c,c-b-1,a,m);
ll w1=n*(m+1)%Mod,w2=n*(n+1)%Mod,w3=m+1;
if(w3>=Mod)w3%=Mod;
ans.f=(w1-res.f)%Mod;if(ans.f<0)ans.f+=Mod;
ans.g=((w1*w3)%Mod-((res.h*2ll%Mod+res.f)%Mod))%Mod;if(ans.g<0)ans.g+=Mod;
ans.h=((w2*w3)%Mod-(res.f+res.g)%Mod)%Mod*inv2%Mod;if(ans.h<0)ans.h+=Mod;
return ans;
}
int a,b,c,n,T;
int main(){
for(scanf("%d",&T);T--;){scanf("%d%d%d%d",&n,&a,&b,&c);calc(a,b,c,n).out();}
return 0;
}
我们其实可以求取更加一般化的式子,如这道模板题【IN-loj】
题意就是多组询问,给定 k 1 , k 2 , a , b , c , n k_1,k_2,a,b,c,n k1,k2,a,b,c,n求下面式子在 m o d 998244353 \rm mod\ 998244353 mod 998244353意义下的值。
∑ i = 0 n i k 1 ⌊ a i + b c ⌋ k 2 \sum_{i=0}^ni^{k_1}\left\lfloor\frac{ai+b}{c}\right\rfloor^{k_2} i=0∑nik1⌊cai+b⌋k2
数据范围见原题面。
- 当 k 1 = 0 , k 2 = 1 k_1=0,k_2=1 k1=0,k2=1时,就是 f f f函数。
- 当 k 1 = 0 , k 2 = 2 k_1=0,k_2=2 k1=0,k2=2时,就是 h h h函数。
- 当 k 1 = 1 , k 2 = 1 k_1=1,k_2=1 k1=1,k2=1时,就是 g g g函数。
那么当 k 1 , k 2 k_1,k_2 k1,k2不为上面的那些情况的时候应该怎么办呢?
我们还是按照套路来分析,我们令 F ( k 1 , k 2 , a , b , c , n ) = ∑ i = 0 n i k 1 ⌊ a i + b c ⌋ k 2 F(k_1,k_2,a,b,c,n)=\sum_{i=0}^ni^{k_1}\left\lfloor\frac{ai+b}{c}\right\rfloor^{k_2} F(k1,k2,a,b,c,n)=∑i=0nik1⌊cai+b⌋k2:
- 当 a ≥ c , b ≥ c a\geq c,b\geq c a≥c,b≥c时:
F ( k 1 , k 2 , a , b , c , n ) = ∑ i = 0 n i k 1 ( ⌊ a c ⌋ i + ⌊ b c ⌋ + ⌊ ( a % c ) i + ( b % c ) c ⌋ ) k 2 F(k_1,k_2,a,b,c,n)=\sum_{i=0}^ni^{k_1}\left(\left\lfloor\frac{a}{c}\right\rfloor i+\left\lfloor\frac{b}{c}\right\rfloor+\left\lfloor\frac{(a\%c)i+(b\%c)}{c}\right\rfloor\right)^{k_2} F(k1,k2,a,b,c,n)=i=0∑nik1(⌊ca⌋i+⌊cb⌋+⌊c(a%c)i+(b%c)⌋)k2
用二项式定理,我们可以将后面的括号展开得到:
用二项式定理推导一下可以得到
( a + b + c ) n = ∑ i + j + k = n C n i C n − i j a i b j c k (a+b+c)^n=\sum_{i+j+k=n}C_{n}^iC_{n-i}^ja^ib^jc^k (a+b+c)n=∑i+j+k=nCniCn−ijaibjck
F ( k 1 , k 2 , a , b , c , n ) = ∑ I = 0 n ∑ i + j + k = k 2 C k 2 i C k 2 − i j ⌊ a c ⌋ i ⌊ b c ⌋ j ( I k 1 + i ) ⌊ ( a % c ) I + ( b % c ) c ⌋ k = ∑ i + j + k = k 2 C k 2 i C k 2 − i j ⌊ a c ⌋ i ⌊ b c ⌋ j ∑ I = 0 n ( I k 1 + i ) ⌊ ( a % c ) I + ( b % c ) c ⌋ k 0 ≤ i , j , k F(k_1,k_2,a,b,c,n)=\sum_{I=0}^n\sum_{i+j+k=k_2}C_{k_2}^iC_{k_2-i}^j\left\lfloor\frac{a}{c}\right\rfloor^i\left\lfloor\frac{b}{c}\right\rfloor^j\left(I^{k_1+i}\right)\left\lfloor\frac{(a\%c)I+(b\%c)}{c}\right\rfloor^{k} \\ =\sum_{i+j+k=k_2}C_{k_2}^iC_{k_2-i}^j\left\lfloor\frac{a}{c}\right\rfloor^i\left\lfloor\frac{b}{c}\right\rfloor^j\sum_{I=0}^n\left(I^{k_1+i}\right)\left\lfloor\frac{(a\%c)I+(b\%c)}{c}\right\rfloor^{k} \\ 0\leq i,j,k F(k1,k2,a,b,c,n)=I=0∑ni+j+k=k2∑Ck2iCk2−ij⌊ca⌋i⌊cb⌋j(Ik1+i)⌊c(a%c)I+(b%c)⌋k=i+j+k=k2∑Ck2iCk2−ij⌊ca⌋i⌊cb⌋jI=0∑n(Ik1+i)⌊c(a%c)I+(b%c)⌋k0≤i,j,k
我们可以发现,最后面那堆等于 F ( k 1 + i , k , a % c , b % c , c , n ) F(k_1+i,k,a\%c,b\%c,c,n) F(k1+i,k,a%c,b%c,c,n),所以递归处理即可。
- 当 a < c , b < c a<c,b<c a<c,b<c的时候:
我们知道 x k = ∑ i = 0 x − 1 ( i + 1 ) k − i k x^k=\sum_{i=0}^{x-1}(i+1)^k-i^k xk=∑i=0x−1(i+1)k−ik
因为其等于: x k − ( x − 1 ) k + ( x − 1 ) k − ( x − 2 ) k + ⋯ − 0 k = x k − 0 = x k x^k-(x-1)^k+(x-1)^k-(x-2)^k+\cdots-0^k=x^k-0=x^k xk−(x−1)k+(x−1)k−(x−2)k+⋯−0k=xk−0=xk
那么我们用其来变换原式得到:
F ( k 1 , k 2 , a , b , c , n ) = ∑ i = 0 n i k 1 ∑ j = 0 ⌊ a i + b c ⌋ − 1 ( j + 1 ) k 2 − j k 2 F(k_1,k_2,a,b,c,n)=\sum_{i=0}^ni^{k_1}\sum_{j=0}^{\left\lfloor\frac{ai+b}{c}\right\rfloor-1}(j+1)^{k_2}-j^{k_2} F(k1,k2,a,b,c,n)=i=0∑nik1j=0∑⌊cai+b⌋−1(j+1)k2−jk2
我们交换枚举顺序可以得到( m = ⌊ a n + b c ⌋ − 1 m=\left\lfloor\frac{an+b}{c}\right\rfloor-1 m=⌊can+b⌋−1):
F ( k 1 , k 2 , a , b , c , n ) = ∑ j = 0 m ( ( j + 1 ) k 2 − j k 2 ) ∑ i = 0 n i k 1 [ j ≤ ⌊ a i + b c ⌋ ] = ∑ j = 0 m ( ( j + 1 ) k 2 − j k 2 ) ∑ i = 0 n i k 1 [ i < ⌊ j c + c − b − 1 a ⌋ ] = ∑ j = 0 m ( ( j + 1 ) k 2 − j k 2 ) ( ∑ i = 0 n i k 1 − ∑ i = 0 ⌊ j c + c − b − 1 a ⌋ i k 1 ) \begin{aligned} F(k_1,k_2,a,b,c,n)=&\sum_{j=0}^{m}\left((j+1)^{k_2}-j^{k_2}\right)\sum_{i=0}^ni^{k_1}[j\leq\left\lfloor\frac{ai+b}{c}\right\rfloor] \\ =&\sum_{j=0}^{m}\left((j+1)^{k_2}-j^{k_2}\right)\sum_{i=0}^ni^{k_1}[i<\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor] \\ =&\sum_{j=0}^{m}\left((j+1)^{k_2}-j^{k_2}\right)\left(\sum_{i=0}^{n}i^{k_1}-\sum_{i=0}^{\lfloor\frac{jc+c-b-1}{a}\rfloor}i^{k_1}\right) \end{aligned} F(k1,k2,a,b,c,n)===j=0∑m((j+1)k2−jk2)i=0∑nik1[j≤⌊cai+b⌋]j=0∑m((j+1)k2−jk2)i=0∑nik1[i<⌊ajc+c−b−1⌋]j=0∑m((j+1)k2−jk2)⎝⎛i=0∑nik1−i=0∑⌊ajc+c−b−1⌋ik1⎠⎞
我们接下来将前面那一堆(也就是相当于 ( m + 1 ) k 2 (m+1)^{k_2} (m+1)k2)乘进后面,得到:
F ( k 1 , k 2 , a , b , c , n ) = ∑ j = 0 m ( ( j + 1 ) k 2 − j k 2 ) ∑ i = 0 n i k 1 − ∑ j = 0 m ( ( j + 1 ) k 2 − j k 2 ) ∑ i = 0 ⌊ j c + c − b − 1 a ⌋ i k 1 = ( m + 1 ) k 2 ∑ i = 0 n i k 1 − ∑ j = 0 m ( ( j + 1 ) k 2 − j k 2 ) ∑ i = 0 ⌊ j c + c − b − 1 a ⌋ i k 1 \begin{aligned} F(k_1,k_2,a,b,c,n)=&\sum_{j=0}^{m}\left((j+1)^{k_2}-j^{k_2}\right)\sum_{i=0}^n i^{k_1}-\sum_{j=0}^{m}\left((j+1)^{k_2}-j^{k_2}\right)\sum_{i=0}^{\lfloor\frac{jc+c-b-1}{a}\rfloor}i^{k_1} \\ =&(m+1)^{k_2}\sum_{i=0}^n i^{k_1}-\sum_{j=0}^{m}\left((j+1)^{k_2}-j^{k_2}\right)\sum_{i=0}^{\lfloor\frac{jc+c-b-1}{a}\rfloor}i^{k_1} \end{aligned} F(k1,k2,a,b,c,n)==j=0∑m((j+1)k2−jk2)i=0∑nik1−j=0∑m((j+1)k2−jk2)i=0∑⌊ajc+c−b−1⌋ik1(m+1)k2i=0∑nik1−j=0∑m((j+1)k2−jk2)i=0∑⌊ajc+c−b−1⌋ik1
而我们知道,关于自然数幂的前缀和是一个关于幂次+1的多项式,所以我们可以用拉格朗日插值(或者高斯消元)把其系数求出来,然后就可以带入到后面那一堆,再用二项式定理展开,得到:
假设 ∑ i = 0 k + 1 a k , i x i = ∑ i = 0 x i k \sum_{i=0}^{k+1}a_{k,i}x^i=\sum_{i=0}^xi^k ∑i=0k+1ak,ixi=∑i=0xik
F ( k 1 , k 2 , a , b , c , n ) = ( m + 1 ) k 2 ∑ i = 0 n i k 1 − ∑ j = 0 m ( ( j + 1 ) k 2 − j k 2 ) ∑ i = 0 ⌊ j c + c − b − 1 a ⌋ i k 1 = ( m + 1 ) k 2 ∑ i = 0 n i k 1 − ∑ k = 0 k 2 − 1 ( ∑ j = 0 m C k 2 k j k ⋅ ∑ i = 0 ⌊ j c + c − b − 1 a ⌋ i k 1 ) = ( m + 1 ) k 2 ∑ i = 0 n i k 1 − ∑ k = 0 k 2 − 1 ( ∑ j = 0 m C k 2 k j k ⋅ ∑ i = 0 k 1 + 1 a k 1 , i ( ⌊ j c + c − b − 1 a ⌋ ) i ) = ( m + 1 ) k 2 ∑ i = 0 n i k 1 − ∑ k = 0 k 2 − 1 ∑ i = 0 k 1 + 1 C k 2 k a k 1 , i ⋅ ∑ j = 0 m j k ( ⌊ j c + c − b − 1 a ⌋ ) i = ( m + 1 ) k 2 ∑ i = 0 n i k 1 − ∑ k = 0 k 2 − 1 ∑ i = 0 k 1 + 1 C k 2 k a k 1 , i ⋅ F ( k , i , c , c − b − 1 , a , m ) \begin{aligned} F(k_1,k_2,a,b,c,n)=&(m+1)^{k_2}\sum_{i=0}^n i^{k_1}-\sum_{j=0}^{m}\left((j+1)^{k_2}-j^{k_2}\right)\sum_{i=0}^{\lfloor\frac{jc+c-b-1}{a}\rfloor}i^{k_1} \\ =&(m+1)^{k_2}\sum_{i=0}^n i^{k_1}-\sum_{k=0}^{k_2-1}\left(\sum_{j=0}^mC_{k_2}^kj^k\cdot \sum_{i=0}^{\lfloor\frac{jc+c-b-1}{a}\rfloor}i^{k_1}\right) \\ =&(m+1)^{k_2}\sum_{i=0}^n i^{k_1}-\sum_{k=0}^{k_2-1}\left(\sum_{j=0}^mC_{k_2}^kj^k\cdot \sum_{i=0}^{k_1+1}a_{k_1,i}\left(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\right)^i\right) \\ =&(m+1)^{k_2}\sum_{i=0}^n i^{k_1}-\sum_{k=0}^{k_2-1}\sum_{i=0}^{k_1+1}C_{k_2}^ka_{k_1,i}\cdot \sum_{j=0}^mj^k\left(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\right)^i \\ =&(m+1)^{k_2}\sum_{i=0}^n i^{k_1}-\sum_{k=0}^{k_2-1}\sum_{i=0}^{k_1+1}C_{k_2}^ka_{k_1,i}\cdot F(k,i,c,c-b-1,a,m) \end{aligned} F(k1,k2,a,b,c,n)=====(m+1)k2i=0∑nik1−j=0∑m((j+1)k2−jk2)i=0∑⌊ajc+c−b−1⌋ik1(m+1)k2i=0∑nik1−k=0∑k2−1⎝⎛j=0∑mCk2kjk⋅i=0∑⌊ajc+c−b−1⌋ik1⎠⎞(m+1)k2i=0∑nik1−k=0∑k2−1(j=0∑mCk2kjk⋅i=0∑k1+1ak1,i(⌊ajc+c−b−1⌋)i)(m+1)k2i=0∑nik1−k=0∑k2−1i=0∑k1+1Ck2kak1,i⋅j=0∑mjk(⌊ajc+c−b−1⌋)i(m+1)k2i=0∑nik1−k=0∑k2−1i=0∑k1+1Ck2kak1,i⋅F(k,i,c,c−b−1,a,m)
其中,有一步是这样变换的:
∑ i = 0 x − 1 ( i + 1 ) k − i k = ∑ i = 0 x − 1 ∑ j = 0 k C k j i j − i k = ∑ i = 0 x − 1 ∑ j = 0 k − 1 C k j i j = ∑ j = 0 k − 1 ( ∑ i = 0 x − 1 C k j i j ) \sum_{i=0}^{x-1}(i+1)^k-i^k=\sum_{i=0}^{x-1}\sum_{j=0}^kC_{k}^ji^j-i^k \\=\sum_{i=0}^{x-1}\sum_{j=0}^{k-1}C_{k}^{j}i^j \\=\sum_{j=0}^{k-1}\left(\sum_{i=0}^{x-1}C_{k}^ji^j\right) i=0∑x−1(i+1)k−ik=i=0∑x−1j=0∑kCkjij−ik=i=0∑x−1j=0∑k−1Ckjij=j=0∑k−1(i=0∑x−1Ckjij)
那么,这个和前面的其实一样,递归计算就好啦,只不过要提前预处理一下系数和组合数。
k 1 , k 2 k_1,k_2 k1,k2比较小,所以每次算的时候暴力枚举一下(或者可以用 F F T FFT FFT之类的优化一下)就行了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=13;
const ll Mod=1e9+7;
ll y[M],C[M][M],F[M][M][44];
ll fpow(ll a,ll b=Mod-2){
a%=Mod;if(a<0)a+=Mod;ll res=1;for(;b;b>>=1,a=(a*a)%Mod)if(b&1)res=(res*a)%Mod;
return res;
}
struct Ply{
ll x[M];
void clear(){memset(x,0,sizeof(x));}
Ply(){memset(x,0,sizeof(x));}
Ply operator +(const Ply &a)const{
Ply ans;for(int i=0;i<M;i++)ans.x[i]=(x[i]+a.x[i])%Mod;
return ans;
}
Ply operator *(const Ply &a)const{
Ply ans;
for(int i=0;i<M;i++)for(int j=0;i+j<M;j++)
ans.x[i+j]=(ans.x[i+j]+x[i]*a.x[j]%Mod)%Mod;
return ans;
}
ll operator ()(ll a,int b){
ll ans=x[b+1];for(int i=b;i>=0;i--)ans=(ans*a%Mod+x[i])%Mod;
return ans;
}
}A[M],B[M];
void calc(Ply &a,int n){
Ply xx,yy;
for(int i=0;i<=n;i++){
xx.x[0]=y[i];
for(int j=0;j<=n;j++)if(i^j)xx.x[0]=xx.x[0]*fpow(i-j)%Mod;
for(int j=0;j<=n;j++)if(j^i){yy.x[0]=Mod-j;yy.x[1]=1;xx=xx*yy;}
a=a+xx;xx.clear();
}
}
ll f(int k1,int k2,ll a,ll b,ll c,ll n,int d=0){
if(~F[k1][k2][d]) return F[k1][k2][d];
ll ans=0;
if(!a) ans=B[k1](n,k1)*fpow(b/c,k2)%Mod;
else if(!k2) ans=B[k1](n,k1);
else if(a>=c||b>=c){
int x=a/c,y=b/c;a%=c;b%=c;
for(ll i=0,X=1;i<=k2;i++,X=(X*x)%Mod){
for(ll j=0,Y=X;i+j<=k2;j++,Y=Y*y%Mod){
ans=(ans+f(k1+i,k2-i-j,a,b,c,n,d+1)*C[k2][i]%Mod*C[k2-i][j]%Mod*Y%Mod)%Mod;
}
}
}else{
int m=(a*n+b)/c;--m;
ans=A[k2](m,k2);
ans=ans*B[k1](n,k1)%Mod;
for(int j=0;j<k2;j++)for(int i=0;i<=k1+1;i++){
ans=(ans-f(j,i,c,c-b-1,a,m,d+1)*C[k2][j]%Mod*B[k1].x[i]%Mod)%Mod;
}
}
if(ans<0)(ans%=Mod)+=Mod;ans%=Mod;
return F[k1][k2][d]=ans;
}
void init(){
C[0][0]=1;
for(int i=1;i<=10;i++){
C[i][0]=C[i][i]=1;
for(int j=1;j<i;j++){
C[i][j]=(C[i-1][j]+C[i-1][j-1])%Mod;
}
}
for(int i=0;i<=10;i++){
if(i)y[0]=1;
for(int j=1;j<=i+1;j++){
y[j]=(y[j-1]+fpow(j+1,i)-fpow(j,i))%Mod;
if(y[j]<0)y[j]+=Mod;
}
calc(A[i],i+1);
if(!i)y[0]=1;else y[0]=0;
for(int j=1;j<=i+1;j++)y[j]=(y[j-1]+fpow(j,i))%Mod;
calc(B[i],i+1);
}
}
int T,a,b,c,n,k1,k2;
int main(){
init();
for(scanf("%d",&T);T--;){
scanf("%d%d%d%d%d%d",&n,&a,&b,&c,&k1,&k2);
memset(F,-1,sizeof(F));
printf("%d\n",f(k1,k2,a,b,c,n));
}
return 0;
}
题目:
LOJ模板题的另外两个讲解: