题意:
给p,q,p/q代表在只有红黑两色的几只袜子中,取到一双红色袜子的概率。
求在红黑两种袜子总只数最小的情况下,红袜子与黑袜子的只数。
解析:
设红袜子x只,黑袜子y只。
则 p / q = C(x, 2) / C(x + y, 2) = x * ( x - 1 ) / ( x + y ) * ( x + y - 1)。
枚举分母中的 total = x + y,总只数从2到50000,满足q | total。每次可以求出分子 t = total * (total - 1) / q * p。
只要验证 t是否能拆成x * (x- 1)就行了。
验证方法是把 t 开方,向上下取整,看是否乘积为 t 就行了。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
using namespace std;
#define uint unsigned int
uint p, q;
uint gcd(uint a, uint b)
{
return b ? gcd(b, a % b) : a;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
while (scanf("%u%u", &p, &q))
{
if (!p && !q)
break;
if (p == 0)
{
printf("0 2\n");
}
else
{
bool flag = false;
uint d = gcd(p, q);
p /= d;
q /= d;
for (uint total = 2; total <= 50000; total++)
{
uint fenmu = total * (total - 1);
if (fenmu % q == 0)
{
uint fenzi = fenmu / q * p;
uint lo = floor(sqrt(fenzi));
uint hi = ceil(sqrt(fenzi));
if (lo != hi && lo * hi == fenzi)
{
printf("%u %u\n", hi, total - hi);
flag = true;
break;
}
}
}
if (!flag)
printf("impossible\n");
}
}
return 0;
}