类欧几里得算法学习笔记

这个东西看起来好恐怖啊QAQ.jpg搞了几天,QWQ


其实类欧几里得算法,就是和欧几里得算法类似(欧几里得算法就是gcd那一堆啦),但是其实只有时间复杂度的证明是和gcd一样的,其它的都完全不同,emmmm。


先前置两道例题:【luoug-T36097 整点与质数】【[COCI2009-2010#1] ALADIN
】【讲解by hdxrie

其实这个就是一个十分简单的类欧算法的应用
以前做到的时候还不知道,现在学了才知道,QAQ


我们可以从一个简单的式子来入门,并对其套路有一定的了解。

T ≤ 1 0 5 T\leq 10^5 T105组询问,每组对于给定的 n ≤ 1 0 9 n\leq 10^9 n109求下面式子在 m o d   998244353 \rm mod\ 998244353 mod 998244353意义下的值 ( a , b ≥ 0 , c > 0 ) (a,b\geq 0,c>0) (a,b0,c>0)

∑ i = 0 n ⌊ a i + b c ⌋ \sum_{i=0}^n\left\lfloor\frac{ai+b}{c}\right\rfloor i=0ncai+b

其实前面的 ⌊ i p q ⌋ \left\lfloor\frac{ip}{q}\right\rfloor qip就是这个式子的简化版, b = 0 b=0 b=0

显然这个不能直接 O ( n ) O(n) O(n)算,或者除法分块,所以我们要另寻它路。

首先我们可以分成两步考虑:

  1. a ≥ c a\geq c ac或者 b ≥ c b\geq c bc

此时,我们显然可以将原式写成:

∑ 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=0n(cai+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 cai=0ni+i=0ncb+i=0nc(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=0ncai+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)=ca2n×(n+1)+(n+1)cb+f(a%c,b%c,c,n)

此时我们就把问题从 a ≥ c , b ≥ c a\geq c,b\geq c ac,bc转换 a , b &lt; c a,b&lt;c a,b<c的情况了。

  1. 那么显然另外一种情况就是 a &lt; c a&lt;c a<c b &lt; c b&lt;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+b1):

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=0nj=1m+1[jcai+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 ab时也满足 a ⩽ b a\leqslant b ab,所以变换时可以把向下取整符号去掉。

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 &gt; j c + c − b − 1 ] = ∑ j = 0 m ∑ i = 0 n [ i &gt; ⌊ j c + c − b − 1 a ⌋ ] \begin{aligned} f(a,b,c,n)=&amp;\sum_{j=1}^{m+1}\sum_{i=0}^n[j\leqslant \left\lfloor\frac{ai+b}{c}\right\rfloor] \\ =&amp;\sum_{j=0}^{m}\sum_{i=0}^n[j+1\leqslant \left\lfloor\frac{ai+b}{c}\right\rfloor] \\ =&amp;\sum_{j=0}^{m}\sum_{i=0}^n[j+1\leqslant \frac{ai+b}{c}] \\ =&amp;\sum_{j=0}^{m}\sum_{i=0}^n[jc+c\leqslant ai+b] \\ =&amp;\sum_{j=0}^{m}\sum_{i=0}^n[ai\geqslant jc+c-b] \\ =&amp;\sum_{j=0}^{m}\sum_{i=0}^n[ai&gt;jc+c-b-1] \\ =&amp;\sum_{j=0}^{m}\sum_{i=0}^n[i&gt;\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor] \end{aligned} f(a,b,c,n)=======j=1m+1i=0n[jcai+b]j=0mi=0n[j+1cai+b]j=0mi=0n[j+1cai+b]j=0mi=0n[jc+cai+b]j=0mi=0n[aijc+cb]j=0mi=0n[ai>jc+cb1]j=0mi=0n[i>ajc+cb1]

由于在 i ∈ [ 0 , n ] i\in[0,n] i[0,n]中的 i &gt; ⌊ j c + c − b − 1 a ⌋ i&gt;\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor i>ajc+cb1的只有 ⌊ j c + c − b − 1 a ⌋ ∼ n \left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\sim n ajc+cb1n,所以进而化简得:

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)=&amp;\sum_{j=0}^{m}\left(n-\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor\right) \\ =&amp;\sum_{j=0}^{m}n-\sum_{j=0}^{m}\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor \\ =&amp;\ n\times (m+1)-f(c,c-b-1,a,m) \end{aligned} f(a,b,c,n)===j=0m(najc+cb1)j=0mnj=0majc+cb1 n×(m+1)f(c,cb1,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,cb1,a,can+b1),又将问题变小了。

那么边界就是当:

  • 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 &lt; c   a n d   b &lt; c f(a,b,c,n)=\begin{cases}\lfloor\frac{b}{c}\rfloor&amp;n=0\\ (n+1)\times \lfloor\frac{b}{c}\rfloor&amp;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)&amp;a\geqslant c\ or\ b\geqslant c\\ n\times \left\lfloor\frac{an+b}{c}\right\rfloor-f(c,c-b-1,a,m)&amp;a&lt;c\ and\ b&lt;c\end{cases} f(a,b,c,n)=cb(n+1)×cbca2n×(n+1)+(n+1)cb+f(a%c,b%c,c,n)n×can+bf(c,cb1,a,m)n=0a=0ac or bca<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 ac,bc的时候只需 O ( 1 ) O(1) O(1)就转移到了 a &lt; c , b &lt; c a&lt;c,b&lt;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,cb1,a,can+b1)这个就十分类似于欧几里得算法的更相减损术,直到 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=0n(cai+b)2

∑ i = 0 n i ⌊ a i + b c ⌋ \sum_{i=0}^ni\left\lfloor\frac{ai+b}{c}\right\rfloor i=0nicai+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=0nicai+b


那么我们先来看 h h h的求法,和 f f f类似(其实类欧的套路都差不多是这样),我们分两块考虑:

  1. a ≥ c a\geq c ac或者 b ≥ c b\geq c bc时:

显然同理有:

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=0n(cai+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=0n(cai)2+i=0n(cb)2+i=0n(c(a%c)i+(b%c))2+i=0n2caicb+i=0n2cbc(a%c)i+(b%c)+i=0n2caic(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)+2cacb2n×(n+1)+2cbf(a%c,b%c,c,n)+2cag(a%c,b%c,c,n)

递归处理就可以了(假设我们现在知道 g g g如何计算)。

  1. 我们继续考虑当 a &lt; c , b &lt; c a&lt;c,b&lt;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=0n(j=1m+1[jcai+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 &gt; j c + c − b − 1 ] ) × ( ∑ k = 0 m [ a i &gt; k c + c − b − 1 ] ) \begin{aligned} h(a,b,c,n)=&amp;\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) \\ =&amp;\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) \\ =&amp;\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) \\ =&amp;\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) \\ =&amp;\sum_{i=0}^n\left(\sum_{j=0}^{m}[ai&gt; jc+c-b-1]\right)\times \left(\sum_{k=0}^{m}[ai&gt; {kc+c-b-1}]\right) \end{aligned} h(a,b,c,n)=====i=0n(j=1m+1[jcai+b])×(k=1m+1[kcai+b])i=0n(j=0m[j+1cai+b])×(k=0m[k+1cai+b])i=0n(j=0m[jc+cai+b])×(k=0m[kc+cai+b])i=0n(j=0m[aijc+cb])×(k=0m[aikc+cb])i=0n(j=0m[ai>jc+cb1])×(k=0m[ai>kc+cb1])

然后我们同理,交换枚举顺序,可以得到:

h ( a , b , c , n ) = ∑ j = 0 m ∑ k = 0 m ∑ i = 0 n [ a i &gt; max ⁡ ( j c − b − 1 , k c − b − 1 ) ] = ∑ j = 0 m ∑ k = 0 m ∑ i = 0 n [ i &gt; max ⁡ ( ⌊ j c + c − b − 1 a ⌋ , ⌊ k c + c − b − 1 a ⌋ ) ] \begin{aligned} h(a,b,c,n)=&amp;\sum_{j=0}^m\sum_{k=0}^m\sum_{i=0}^n[ai&gt;\max(jc-b-1,kc-b-1)] \\ =&amp;\sum_{j=0}^m\sum_{k=0}^m\sum_{i=0}^n[i&gt;\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=0mk=0mi=0n[ai>max(jcb1,kcb1)]j=0mk=0mi=0n[i>max(ajc+cb1,akc+cb1)]

同样, i ∈ [ 0 , n ] i\in[0,n] i[0,n] i &gt; max ⁡ ( ⌊ j c + c − b − 1 a ⌋ , ⌊ k c + c − b − 1 a ⌋ ) i&gt;\max(\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor,\left\lfloor\frac{kc+c-b-1}{a}\right\rfloor) i>max(ajc+cb1,akc+cb1)的只有 &gt; max ⁡ ( ⌊ j c + c − b − 1 a ⌋ , ⌊ k c + c − b − 1 a ⌋ ) ∼ n &gt;\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+cb1,akc+cb1)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)=&amp;\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) \\ =&amp; 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=0mk=0m(nmax(ajc+cb1,akc+cb1))n(m+1)2j=0mk=0mmax(ajc+cb1,akc+cb1)

这里的 max ⁡ \max max不好处理,但是我们可以通过枚举当前这个是 max ⁡ \max max的贡献,首先 j ⩾ k j\geqslant k jk的部分为:

∑ 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=0m(j+1)ajc+cb1

因为对于每个 j j j,都有 0 ∼ j 0\sim j 0j也就是 j + 1 j+1 j+1 k k k比它小,所以每个的贡献次数是 j + 1 j+1 j+1次。

那么同理对于 j ⩽ k j\leqslant k jk的部分就是:
∑ 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=0m(k+1)akc+cb1

但是这两个加起来,会把 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=0majc+cb1

那么原式就可以变成:

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)=&amp;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) \\ =&amp;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) \\ =&amp;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)2j=0mk=0mmax(ajc+cb1,akc+cb1)n(m+1)2(j=0m(j+1)ajc+cb1+k=0m(k+1)akc+cb1j=0majc+cb1)n(m+1)2(2j=0m(j+1)ajc+cb1j=0majc+cb1)

我们把 ( 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)=&amp;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) \\ =&amp;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) \\ =&amp;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(2j=0mjajc+cb1+2j=0majc+cb1j=0majc+cb1)n(m+1)2(2j=0mjajc+cb1+j=0majc+cb1)n(m+1)22g(c,cb1,a,m)f(c,cb1,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 &lt; c   a n d   b &lt; c h(a,b,c,n)=\begin{cases}\left(\frac{b}{c}\right)^2&amp;n=0\\ (n+1)\times \left(\frac{b}{c}\right)^2&amp;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)&amp;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)&amp;a&lt;c\ and\ b&lt;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)+2cacb2n(n+1)+2cbf(a%c,b%c,c,n)+2cag(a%c,b%c,c,n)n(m+1)22g(c,cb1,a,m)f(c,cb1,a,m)n=0a=0ac or bca<c and b<c

代码同样十分好写,仿照上面的即可,这里就不写了。


接下来只剩下对于 g g g的求法了。

g g g相对 h h h来说就很好变换了,直接跟着套路走:

  1. a ⩾ c , b ⩾ c a\geqslant c,b\geqslant c ac,bc时:

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)=&amp;\sum_{i=0}^ni\left\lfloor\frac{ai+b}{c}\right\rfloor \\ =&amp;\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 \\ =&amp;\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=0nicai+bi=0ncai2+cbi+ic(a%c)i+(b%c)ca6n(n+1)(2n+1)+cb2n(n+1)+g(a%c,b%c,c,n)

  1. a &lt; c , b &lt; c a&lt;c,b&lt;c a<c,b<c

根据套路,我们转换成这个形式:

g ( a , b , c , n ) = ∑ j = 0 m ∑ i = 0 n i [ i &gt; ⌊ 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)=&amp;\sum_{j=0}^{m}\sum_{i=0}^ni[i&gt;\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor] \\ =&amp;\sum_{j=0}^{m}\sum_{i=\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor+1}^ni \\ =&amp;\sum_{j=0}^{m}\left(\sum_{i=0}^ni-\sum_{i=0}^{\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor}i\right) \\ =&amp;\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} \\ =&amp;\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) \\ =&amp;\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=0mi=0ni[i>ajc+cb1]j=0mi=ajc+cb1+1nij=0mi=0nii=0ajc+cb1ij=0m2n(n+1)2ajc+cb1(ajc+cb1+1)21(n(n+1)(m+1)j=0m(ajc+cb1)2ajc+cb1)21(n(n+1)(m+1)h(c,cb1,a,m)f(c,cb1,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 &lt; c   a n d   b &lt; c g(a,b,c,n)=\begin{cases}0&amp;n=0\\ \lfloor\frac{b}{c}\rfloor(\frac{n(n+1)}{2})&amp;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)&amp;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)&amp; a&lt;c\ and\ b&lt;c\end{cases} g(a,b,c,n)=0cb(2n(n+1))ca6n(n+1)(2n+1)+cb2n(n+1)+g(a%c,b%c,c,n)21(n(n+1)(m+1)h(c,cb1,a,m)f(c,cb1,a,m))n=0a=0ac or bca<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=0nik1cai+bk2

数据范围见原题面。

  • 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=0nik1cai+bk2

  • a ≥ c , b ≥ c a\geq c,b\geq c ac,bc时:

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=0nik1(cai+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=nCniCnijaibjck

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=0ni+j+k=k2Ck2iCk2ijcaicbj(Ik1+i)c(a%c)I+(b%c)k=i+j+k=k2Ck2iCk2ijcaicbjI=0n(Ik1+i)c(a%c)I+(b%c)k0i,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 &lt; c , b &lt; c a&lt;c,b&lt;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=0x1(i+1)kik

因为其等于: 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(x1)k+(x1)k(x2)k+0k=xk0=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=0nik1j=0cai+b1(j+1)k2jk2

我们交换枚举顺序可以得到( m = ⌊ a n + b c ⌋ − 1 m=\left\lfloor\frac{an+b}{c}\right\rfloor-1 m=can+b1):

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 &lt; ⌊ 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)=&amp;\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] \\ =&amp;\sum_{j=0}^{m}\left((j+1)^{k_2}-j^{k_2}\right)\sum_{i=0}^ni^{k_1}[i&lt;\left\lfloor\frac{jc+c-b-1}{a}\right\rfloor] \\ =&amp;\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=0m((j+1)k2jk2)i=0nik1[jcai+b]j=0m((j+1)k2jk2)i=0nik1[i<ajc+cb1]j=0m((j+1)k2jk2)i=0nik1i=0ajc+cb1ik1

我们接下来将前面那一堆(也就是相当于 ( 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)=&amp;\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} \\ =&amp;(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=0m((j+1)k2jk2)i=0nik1j=0m((j+1)k2jk2)i=0ajc+cb1ik1(m+1)k2i=0nik1j=0m((j+1)k2jk2)i=0ajc+cb1ik1

而我们知道,关于自然数幂的前缀和是一个关于幂次+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)=&amp;(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} \\ =&amp;(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) \\ =&amp;(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) \\ =&amp;(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 \\ =&amp;(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=0nik1j=0m((j+1)k2jk2)i=0ajc+cb1ik1(m+1)k2i=0nik1k=0k21j=0mCk2kjki=0ajc+cb1ik1(m+1)k2i=0nik1k=0k21(j=0mCk2kjki=0k1+1ak1,i(ajc+cb1)i)(m+1)k2i=0nik1k=0k21i=0k1+1Ck2kak1,ij=0mjk(ajc+cb1)i(m+1)k2i=0nik1k=0k21i=0k1+1Ck2kak1,iF(k,i,c,cb1,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=0x1(i+1)kik=i=0x1j=0kCkjijik=i=0x1j=0k1Ckjij=j=0k1(i=0x1Ckjij)

那么,这个和前面的其实一样,递归计算就好啦,只不过要提前预处理一下系数和组合数。

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模板题的另外两个讲解:


End

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VictoryCzt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值