BZOJ-2987 Earthquake(類歐幾里得演算法)
阿新 • • 發佈:2020-12-01
題目描述
給定 \(A,B,C\),求滿足方程 \(Ax+By\leq C\) 的 非負 整數解 \((x,y)\)(\(A,B\leq 10^9,C\leq \min(A,B)\times 10^9\))。
分析
考慮列舉 \(y\),移項得:\(0\leq y\leq \lfloor\frac{C-Ax}{B}\rfloor\),當 $ x=0$ 時,\(y\) 列舉的上界為 \(\lfloor\frac{C}{A}\rfloor\)。
這相當於求線段 \(y=\frac{C-Ax}{B}(0\leq y\leq \lfloor\frac{C}{A}\rfloor)\) 在第一象限和 \(x,y\)
把斜率為負調整成斜率為正的線段,原來線段的兩端點為 \((0,\frac{C}{B}),(\lfloor\frac{C}{A}\rfloor,\frac{C-A\lfloor\frac{C}{A}\rfloor}{B})\),將兩端點對換,分別為 \((0,\frac{C-A\lfloor\frac{C}{A}\rfloor}{B}),(\lfloor\frac{C}{A}\rfloor,\frac{C}{B})\),此時線段為 \(y=\frac{A}{B}x+\frac{C-A\lfloor\frac{C}{A}\rfloor}{B}=\frac{Ax+C\% A}{B}\)
問題即求(加 \(1\) 是因為 \(x=0\) 時也是合法解):
\[\sum_{i=0}^{\lfloor\frac{C}{A}\rfloor}\Big(\Big\lfloor\frac{Ax+C\%A}{B}\Big\rfloor+1\Big)=\sum_{x=0}^{\lfloor\frac{C}{A}\rfloor}\Big(\Big\lfloor\frac{Ax+C\%A+B}{B}\Big\rfloor\Big) \]考慮一個一般性問題:
\[f(a,b,c,n)=\sum_{i=0}^{n}\Big\lfloor\frac{ai+b}{c}\Big\rfloor \]\(1.\)
\(2.\) 當 \(a<c\) 且 \(b<c\) 時,
可以發現右邊遞迴成為子問題,繼續一輪操作即可。邊界條件:\(a=0\)。
程式碼
#include<bits/stdc++.h>
using namespace std;
long long A,B,C;
long long solve(long long a,long long b,long long c,long long n)
{
if(a==0)
return (n+1)*(b/c);
if(a>=c||b>=c)
return solve(a%c,b%c,c,n)+(a/c)*n*(n+1)/2+(b/c)*(n+1);
long long m=(a*n+b)/c;
return n*m-solve(c,c-b-1,a,m-1);
}
int main()
{
cin>>A>>B>>C;
cout<<solve(A,C%A+B,B,C/A)<<endl;
return 0;
}