UVA10277 - Boastin' Red Socks(枚舉+二分)
題目大意:現在有m只紅襪子,n只黑襪子,這樣總襪子total = n + m;現在給你p, q,確定n和m,使得從這些襪子中取兩隻都是紅襪子的概率等於p/q;如果沒有這樣的n和m滿足要求輸出impossible;
解題思路:m *
(m
- 1) / (total *
(total - 1)) = p /q; 那麼我們只需要枚舉total,就可以解到m。但是會有精度誤差,貌似有解決的辦法,但是覺得沒法理解。後面看了另外的一種題接,二分m,因爲m > 1之後就是單調遞增的。所以只要之前處理掉特殊情況 m = 0,也就是p = 0的情況就可以了。
代碼:
#include <cstdio>
#include <cstring>
#include <cmath>
typedef long long ll;
ll gcd (ll a, ll b) {
return (b == 0) ? a : gcd(b, a%b);
}
int main () {
ll p, q, ans, P, Q;
bool flag;
while (scanf ("%lld%lld", &P, &Q) != EOF && (P || Q)) {
flag = 0;
if (P == 0) {
printf ("0 2\n");
continue;
}
if (P == Q) {
printf("2 0\n");
continue;
}
ans = gcd(P, Q);
P /= ans;
Q /= ans;
ll m, total;
int l, r;
for (total = 3; total <= 50000; total++) {
ll N = total * (total - 1) * P, M;
if (N % Q != 0)
continue;
N /= Q;
l = 1; r = total;
while (l < r) {
m = (l + r) / 2;
M = m * (m - 1);
if (M < N)
l = m + 1;
else if (M > N)
r = m;
else {
flag = 1;
break;
}
}
if (flag)
break;
}
if (flag)
printf ("%lld %lld\n", m, total - m);
else
printf ("impossible\n");
}
return 0;
}