原题展现:
Success Rate
(提供二分做法)
前言
听说是史上最简单蓝题,做了一下。
题意
已知
x
,
y
,
p
,
q
x,y,p,q
x,y,p,q,通过只让
y
y
y 加
1
1
1 或
x
,
y
x,y
x,y 同时加
1
1
1,使得满足:
x
′
y
′
=
p
q
\frac{x'}{y'}=\frac{p}{q}
y′x′=qp
思考
目标状态为
p
q
\frac{p}{q}
qp,考虑到这是个比值,自然
x
′
y
′
=
k
p
k
p
\frac{x'}{y'}=\frac{kp}{kp}
y′x′=kpkp。
明显地,这里的
k
k
k 如果合法,那就一定有更小的
k
k
k。
所以考虑二分。
限制条件呢?
因为无论如何决策, y y y 都会加 1 1 1;而 x x x 不一定每一次决策都加 1 1 1。即 Δ y ≥ Δ x \Delta y\geq \Delta x Δy≥Δx。
所以保证 Δ x ≤ Δ y \Delta x \leq \Delta y Δx≤Δy 就好了。即 k p − x ≤ k q − y kp-x\leq kq-y kp−x≤kq−y。
需要注意的是,有一点需要特判:
-
p
=
0
p=0
p=0 时
- x > 0 x> 0 x>0,输出 − 1 -1 −1
- x = 0 x=0 x=0,输出 0 0 0
代码
考虑到数据范围均小于
1
0
9
10^9
109,所以右端点不可以取太大,否则越界变成负数,右端点取
1
0
10
10^{10}
1010,开个 long long
就好了。
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int x,y,p,q;
bool check(int md)
{
return p*md-x<=q*md-y && p*md>=x;
}
void solve()
{
scanf("%lld%lld%lld%lld",&x,&y,&p,&q);
if(p==0)
{
if(x)
puts("-1");
else
puts("0");
return;
}
int l=1,r=1e10,mid,ans=-1;
while(l<=r)
{
mid=l+r>>1;
if(check(mid))
r=mid-1,ans=mid;
else
l=mid+1;
}
if(ans==-1)
puts("-1");
else
printf("%lld\n",ans*q-y);
}
signed main()
{
signed T;
scanf("%d",&T);
while(T--)
solve();
return 0;
}