类欧几里得
(e.g.) 求(sumlimits_{x=1}^nA^xB^{lfloorfrac{ax+b}{c} floor})
-
把柿子转化成一个操作序列,对于一条直线(左上到右下),碰到一条(y=n) 的横线进行一次操作U,碰到一条(x=n)的竖线进行一次操作(R),碰到整点进行一次操作(UR)。两个操作序列合并就是把前一个的贡献加到后一个序列的答案里(有点像cdq分治?),需要信息支持快速合并。
-
还是看例子:
-
初始化:(curA=I,curB=I,sum=0)
-
两个操作是 (U:curB*=B R:curA*=A,sum+=curA*curB)
-
合并两个序列(x,y)((x)前(y)后),相当于序列(y)的初始化变成了 (curA=x.curA,curB=x.curB)
那么(ans.curA=x.curA*y.curA, ans.curB=x.curB*y.curB, ans.sum=x.sum+x.curA*y.sum*x.curB)
-
具体过程
设函数(solve(n,a,b,c,A,B))
表示值域为(n),直线为(y=lfloor frac{ax+b}{c} floor)横坐标+1填一个(B)操作序列,纵坐标+1填一个(A)操作序列。(A,B)从1开始标号。
可以得到:共有(n)个(B),第(i)个(B)前面共有(lfloor frac{ai+b}{c} floor)个(A)。
每次进行以下操作
-
(a->a\%c,b->b\%c)
-
(e.g.) (solve(3,5,1,3,A,B)->solve(3,2,1,3,A',B'))
(AABABAAB->ABBAB)
-
(a\%=c)带来的变化:(B'=A^{aover c}B)
-
(b\%=c)无影响:
- (i>1)时,考虑第(i)个(B)和第(i-1)个(B),他们两个之间的(A)有(lfloorfrac{ai+b}{c} floor-lfloorfrac{a(i-1)+b}{c} floor=lfloor{aover c} floor)个,所以(b\%=c)无影响
- 如果(i=1),(B)前面就有(lfloorfrac{a+b}{c} floor)个(A),看起来(b%=c)是有影响的,但是因为操作过程中的处理,也可以把他变成无影响(具体见下)
-
-
考虑递归下去,((A,B)->(B,A))
-
推导:考虑第(x)个(A)和其之后第一个(B),假设是序列中的第(y)个(B)(推的时候因为x,y为整数,所以一些向上向下取整是可以直接加或者直接去的)
第(i)个(B)之前共有(lfloorfrac{ai+b}{c} floor)个(A)
[xle lfloorfrac{ay+b}{c} floor ][xle frac{ay+b}{c} ][frac{cx-b}{a}le y ][lceilfrac{cx-b}{a} ceille y ][lfloorfrac{cx-b+a-1}{a} floorle y ][lfloorfrac{cx-b-1}{a} floor< y ]所以第(i)个(A)之前共有(lfloorfrac{ci-b-1}{a} floor)个(B)
-
当(i=0)时,(lfloorfrac{ci-b-1}{a} floor<0),所以要特殊考虑第一个(A),具体做法是(lfloorfrac{ci-b-1}{a} floor->lfloorfrac{c(i+1)-b-1}{a} floor),(A)从0开始标号,然后再把第1个(A)(即现在的第0个(A))和它之前的(B)提出来
-
最后一个(A)之后的(B)也要特殊考虑
-
令(m=lfloor frac{a*n+b}{c} floor,cnt=n-lfloorfrac{c*m-b-1}{a} floor) ((A)的数量,最后一个(A)之后的(B)的数量),
则(solve(n,a,b,c,A,B)-> B^{lfloorfrac{c-b-1}{a} floor}+A+solve(m-1,c,c-b-1,a,B,A)+B^{cnt})
-
-
第一次进入递归的时候要先把((a*0+b)/c)个(A)的影响提出来,而后面因为每次都提出了第一个(A)及其之前的(B),所以相当于把每次((a*0+b)/c)的影响提出来了,所以递归的时候可以直接(b\%=c)