AX+BY

目標就是求滿足AX+BY<=C的(X,Y)對數,即求
x=0y=0[Ax+By<=C]
其中1<=A,B<=1e9,C<=1e9*min(A,B),X>=0,Y>=0

稍微化簡二重和式得到
x=0CACAxB+1
很明顯,式子中的A/B 可以把AB 提出,於是可以化簡爲
x=0CAC(AmodB)xB+1+ABx
考慮歐幾里德算法,現在我們想要把B 放到分子中去而把AmodB 放到分母中去,這樣就可以反覆使用這種方法,但是現在還不能這麼做,因爲現在x 的範圍和y 還不對等,因而現在還不能直接交換xy ,考慮題目的幾何意義,實際上就是求AX+BY<=C 這條直線包圍了多少X>=0,Y>=0 的整數點,當我們把A 轉化成A%B之後,再用原來的限制把圖畫出來,實際意義就變成了讓我們求有多少個整點在AX+BY=C 下方且在X=CA 左邊有多少個整點,爲了把問題轉化爲沒有X限制的問題,我們可以把左下方的矩形單獨拿出來算,之後再把直線向下平移,問題就轉化爲輸入參數爲A,B,C 的子問題,不斷迭代下去,直到A,B中某一個是1,就可以直接計算答案,還有一些小細節,可以參考我的代碼

附上此題鏈接:我是鏈接

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL cal(LL x){
    return x*(x+1)/2;
}
LL solve(LL A,LL B,LL C){
    LL nxt=A%B;
    if(!nxt){
        LL ret=(C/B)*(C/A)-A/B*cal(C/A);
        return ret;
    }
    LL y=(C-nxt*(C/A))/B;
    LL ret=y*(C/A)-A/B*cal(C/A);
    ret+=solve(B,nxt,C-B*y);
    return ret;
}
int main(){
    LL A,B,C;
    cin>>A>>B>>C;
    if(A<B)swap(A,B);
    cout<<solve(A,B,C)+C/A+C/B+1;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章