您的位置:首页 > 其它

CF - 807C. Success Rate - 二分+思维+数学

2017-05-08 21:32 387 查看
1.题目描述:

C. Success Rate

time limit per test
2 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

You are an experienced Codeforces user. Today you found out that during your activity on Codeforces you have made y submissions, out
of which x have been successful. Thus, your current success rate on Codeforces is equal to x / y.

Your favorite rational number in the [0;1] range is p / q.
Now you wonder: what is the smallest number of submissions you have to make if you want your success rate to be p / q?

Input

The first line contains a single integer t (1 ≤ t ≤ 1000) —
the number of test cases.

Each of the next t lines contains four integers x, y, p and q (0 ≤ x ≤ y ≤ 109; 0 ≤ p ≤ q ≤ 109; y > 0; q > 0).

It is guaranteed that p / q is an irreducible fraction.

Hacks. For hacks, an additional constraint of t ≤ 5 must be met.

Output

For each test case, output a single integer equal to the smallest number of submissions you have to make if you want your success rate to be equal to your favorite rational number, or -1 if
this is impossible to achieve.

Example

input
4
3 10 1 2
7 14 3 8
20 70 2 7
5 6 1 1


output
4
10
0
-1


Note

In the first example, you have to make 4 successful submissions. Your success rate will be equal to 7 / 14, or 1 / 2.

In the second example, you have to make 2 successful and 8 unsuccessful submissions. Your success rate will be equal to 9 / 24, or 3 / 8.

In the third example, there is no need to make any new submissions. Your success rate is already equal to 20 / 70, or 2 / 7.

In the fourth example, the only unsuccessful submission breaks your hopes of having the success rate equal to 1.

2.题意概述:

记 AC 率为当前 AC 提交的数量 x / 总提交量 y 。已知最喜欢的 AC 率为 p/q (pq∈[0,1])
。 求最少在提交多少题(AC or NOT)能恰好达到 AC 率为 p/q 。

3.解题思路:

开始是单纯考虑二分submission然后贪心地给AC率,结果样例都过不了。因为这样根本没有单调性可言。我们转化一下问题为求最小的 n 满足
nPnQ=x+ay+b
,其中 a 为新提交的 AC 题数,b 为新提交的题数。那么由于 nP
, nQ,
x+a,
y+b
都为整数,故可将等式化为 nP=x+a
且 nQ=y+b 有
a = nP - x, b = nQ - y。这样对于n,a和b都是单调函数,满足的条件有 a >= 0 且 b >= 0 且 b >= a(交题数必须不小于过题数),这样对n进行二分就能得出答案。做完这题我才真正感受到二分的思想,做二分题应该先确立单调关系,不能一上来就xjb二分check,带着脑袋想问题。

赛后在网上还有根据上面公式直接推出解的数论方法,看来二分也不是最佳选择:

由于 nP
, nQ,
x+a,
y+b
都为整数,故可将等式化为 nP=x+a
且 nQ=y+b
,两个方程三个未知数,故该方程若有解即多解。求最小的 n 。同时,可以考虑到存在额外的条件:0≤(a=nP−x)≤(b=nQ−y)
,化简可得到 n≥⌈xP⌉
且 n≥⌈y−xQ−P⌉
,求两者的最大值即为满足条件的最小的 n。此题求最少的新提交题数,ans=b=nQ−y
。(来源于blog:Codeforces Round #412 C. Success Rate (数论)

4.AC代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 100100
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r - t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
ll x, y, p, q;
bool judge(ll m)
{
ll a = m * p - x;
ll s = m * q - y;
return a >= 0 && s >= 0 && s >= a;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long _begin_time = clock();
#endif
int t;
scanf("%d", &t);
while (t--)
{
scanf("%lld%lld%lld%lld", &x, &y, &p, &q);
ll l = 0, r = INF, ans = -1;
bool flag = 0;
while (l < r)
{
int mid = l + r >> 1;
if (judge(mid))
{
ans = mid;
r = mid;
flag = 1;
}
else
l = mid + 1;
}
printf("%lld\n", flag ? ans * q - y : -1);
}
#ifndef ONLINE_JUDGE
long _end_time = clock();
printf("time = %ld ms.", _end_time - _begin_time);
#endif
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm codeforces