求k大GCD。题意:给三个正整数x,y和k,求x和y的第k大公约数。
我的解题思路:首先根据求最大公约数的原理,k大公约数是最大公约数的因子。那么求k大公约数就转换成为了求最大公约数的第k大因子。可以通过唯一分解定理得到最大公约数的因子个数,然后根据情况判断是否枚举。
我的解题代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long Long;
Long x, y, k;
Long Gcd(Long a, Long b);
Long Factor(Long x); //返回因子个数
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%lld %lld %lld", &x, &y, &k);
Long gcd = Gcd(x, y);
Long fn = Factor(gcd);
if (fn < k) puts("-1");
else if (k == fn) puts("1");
else if (k == 1) printf("%lld\n", gcd);
else if (fn % 2 == 1 && (fn - 1) / 2 == k) printf("%lld\n", (Long)sqrt(gcd + 0.5));
else
{
Long cnt = (Long)sqrt(gcd + 0.5) + 1;
Long times = 0;
for (Long i=1; i<cnt; ++i)
{
if (gcd % i == 0)
{
times++;
if (k == times || k == fn - times + 1)
{
printf("%lld\n", k == times ? gcd / i : i);
break;
}
}
}
}
}
return 0;
}
Long Gcd(Long a, Long b)
{
return b == 0 ? a : Gcd(b, a % b);
}
Long Factor(Long x)
{
Long cnt = (Long)sqrt(x + 0.5) + 1;
Long ans = 1;
for (Long i=2; i<cnt; ++i)
{
if (x % i == 0)
{
Long temp = 0;
while (x % i == 0)
{
x /= i;
temp++;
}
ans *= 1 + temp;
}
}
if (x > 1) ans *= 2;
return ans;
}