目標就是求滿足AX+BY<=C的(X,Y)對數,即求
∑x=0∑y=0[Ax+By<=C]
其中1<=A,B<=1e9,C<=1e9*min(A,B),X>=0,Y>=0
稍微化簡二重和式得到
∑x=0⌊CA⌋⌊C−A∗xB+1⌋
很明顯,式子中的A/B 可以把⌊AB⌋ 提出,於是可以化簡爲∑x=0⌊CA⌋⌊C−(AmodB)∗xB+1+⌊AB⌋∗x⌋
考慮歐幾里德算法,現在我們想要把B 放到分子中去而把AmodB 放到分母中去,這樣就可以反覆使用這種方法,但是現在還不能這麼做,因爲現在x 的範圍和y 還不對等,因而現在還不能直接交換x 和y ,考慮題目的幾何意義,實際上就是求AX+BY<=C 這條直線包圍了多少X>=0,Y>=0 的整數點,當我們把A 轉化成A%B之後,再用原來的限制把圖畫出來,實際意義就變成了讓我們求有多少個整點在A′X+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;
}