【类欧几里得算法】【JZOJ 6025】Cannon

Description

【类欧几里得算法】【JZOJ 6025】Cannon_第1张图片
【类欧几里得算法】【JZOJ 6025】Cannon_第2张图片

Analysis

一个很自然的想法是,由于k很大,我们二分一个分数,统计网格有多少个比它大
先不考虑如何二分分数,假装我们已经得到了分数 a b \dfrac{a}{b} ba,如何统计比它大的个数呢?直线上方整点个数,妈妈我会类欧

类欧

我们要求的是这个 f ( a , b , c , n ) = ∑ i = 0 n ⌊ a i + b c ⌋ f(a,b,c,n)=\sum_{i=0}^n \lfloor \dfrac{ai+b}{c}\rfloor f(a,b,c,n)=i=0ncai+b

Case 1

a ≥ c a\geq c ac b ≥ c b \geq c bc显然可以分离出常数项来,这是trivial的,此时
f ( a , b , c , n ) = f ( a % c , b % c , c , n ) + n ( n + 1 ) a 2 c + ( n + 1 ) b c f(a,b,c,n)=f(a \% c,b\%c,c,n)+\dfrac{n(n+1)a}{2c}+\dfrac{(n+1)b}{c} f(a,b,c,n)=f(a%c,b%c,c,n)+2cn(n+1)a+c(n+1)b
不在话下

Case 2

a < c a<c a<c b < c b<c b<c,把上面那条搬下来,搞一波事情
f ( a , b , c , n ) = ∑ i = 0 n ⌊ a i + b c ⌋ f(a,b,c,n)=\sum_{i=0}^n \lfloor \dfrac{ai+b}{c}\rfloor f(a,b,c,n)=i=0ncai+b
魔幻的一步:令 m = ⌊ a n + b c ⌋ m=\lfloor \dfrac{an+b}{c}\rfloor m=can+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 [\dfrac{ai+b}{c} \geq j] f(a,b,c,n)=i=0nj=1m[cai+bj]
= ∑ i = 0 n ∑ j = 0 m − 1 [ a i ≥ j c + c − b ] =\sum_{i=0}^n \sum_{j=0}^{m-1} [ai \geq jc+c-b] =i=0nj=0m1[aijc+cb]
= ∑ i = 0 n ∑ j = 0 m − 1 [ a i > j c + c − b − 1 ] =\sum_{i=0}^n \sum_{j=0}^{m-1} [ai > jc+c-b-1] =i=0nj=0m1[ai>jc+cb1]
= ∑ i = 0 n ∑ j = 0 m − 1 [ i > j c + c − b − 1 a ] =\sum_{i=0}^n \sum_{j=0}^{m-1} [i > \dfrac{jc+c-b-1}{a}] =i=0nj=0m1[i>ajc+cb1]
左边只与 i i i有关,爽了
= ∑ j = 0 m − 1 n − ⌊ j c + c − b − 1 a ⌋ =\sum_{j=0}^{m-1} n-\lfloor\dfrac{jc+c-b-1}{a}\rfloor =j=0m1najc+cb1
= n m − f ( c , c − b − 1 , a , m − 1 ) =nm-f(c,c-b-1,a,m-1) =nmf(c,cb1,a,m1)
我们发现第一、三个参数在模了之后调换了位置,这类似于欧几里得算法,并且由欧几里得算法知,这么迭代下去复杂度也是一个log

代码

ll f(ll a,ll b,ll c,ll n)//sigma (ai+b)/c
{
	if(a==0) return n*(b/c);
	if(a>=c || b>=c) return f(a%c,b%c,c,n)+n*(n+1)/2*(a/c)+(n+1)*(b/c);
	ll m=(a*n+b)/c;
	return n*m-f(c,c-b-1,a,m-1);
}

二分

然而二分分数是个棘手的问题(听说可以二分实数强转但具体不清楚)
今年WC上讲了一个叫傻逼树(Stern Brocot Tree)的东西来生成所有既约分数的姿势,详见scape鸽鸽的课件
在这棵树上遍历就相当于二分过程啦><
然而并不能一步步走qwq,注意到树的深度是O(n)的,但是这棵树一个性质是,从根走到任意一个分数,拐弯的次数不超过Log次
那么在走的时候二分一下拐点就可以了
单次查询就是3个log的

你可能感兴趣的:(题解,数学)