【類歐幾里得算法】【JZOJ 6025】Cannon

Description

在這裏插入圖片描述
在這裏插入圖片描述

Analysis

一個很自然的想法是,由於k很大,我們二分一個分數,統計網格有多少個比它大
先不考慮如何二分分數,假裝我們已經得到了分數ab\dfrac{a}{b},如何統計比它大的個數呢?直線上整點個數,媽媽我會類歐

類歐

我們要求的是這個f(a,b,c,n)=i=0nai+bcf(a,b,c,n)=\sum_{i=0}^n \lfloor \dfrac{ai+b}{c}\rfloor

Case 1

aca\geq cbcb \geq c顯然可以分離出常數項來,這是trivial的,此時
f(a,b,c,n)=f(a%c,b%c,c,n)+n(n+1)a2c+(n+1)bcf(a,b,c,n)=f(a \% c,b\%c,c,n)+\dfrac{n(n+1)a}{2c}+\dfrac{(n+1)b}{c}
不在話下

Case 2

a<ca<cb<cb<c,把上面那條搬下來,搞一波事情
f(a,b,c,n)=i=0nai+bcf(a,b,c,n)=\sum_{i=0}^n \lfloor \dfrac{ai+b}{c}\rfloor
魔幻的一步:令m=an+bcm=\lfloor \dfrac{an+b}{c}\rfloor
f(a,b,c,n)=i=0nj=1m[ai+bcj]f(a,b,c,n)=\sum_{i=0}^n \sum_{j=1}^m [\dfrac{ai+b}{c} \geq j]
=i=0nj=0m1[aijc+cb]=\sum_{i=0}^n \sum_{j=0}^{m-1} [ai \geq jc+c-b]
=i=0nj=0m1[ai>jc+cb1]=\sum_{i=0}^n \sum_{j=0}^{m-1} [ai > jc+c-b-1]
=i=0nj=0m1[i>jc+cb1a]=\sum_{i=0}^n \sum_{j=0}^{m-1} [i > \dfrac{jc+c-b-1}{a}]
左邊只與ii有關,爽了
=j=0m1njc+cb1a=\sum_{j=0}^{m-1} n-\lfloor\dfrac{jc+c-b-1}{a}\rfloor
=nmf(c,cb1,a,m1)=nm-f(c,c-b-1,a,m-1)
我們發現第一、三個參數在模了之後調換了位置,這類似於歐幾里得算法,並且由歐幾里得算法知,這麼迭代下去複雜度也是一個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的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章