2020牛客多校三 F. Fraction Construction Problem (扩展欧几里得)

题意:
2020牛客多校三 F. Fraction Construction Problem (扩展欧几里得)_第1张图片
题解:扩展欧几里得
d < b, f < b, c > 0, e > 0
分三种情况:
①a、b不互质,求得公因子g,那么一定有 a + g b − g b = a b \frac{a+g}{b}-\frac{g}{b}=\frac{a}{b} ba+gbg=ba

(剩余情况 a b \frac{a}{b} ba一定是最简分式)
②b的相异质因子不超过1个,无解。
给出题解证明:
在这里插入图片描述
③b的相异质因子超过1。
我们可得 c f − d e d f = a b \frac{cf-de}{df}=\frac{a}{b} dfcfde=ba,可令 d f = b df=b df=b,且 g c d ( d , f ) = 1 gcd(d,f)=1 gcd(d,f)=1,那么分子之间直接用扩展欧几里得来做就行了。

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
void exgcd(ll a, ll b, ll& d, ll& x, ll& y) {  //d为a、b的最大公约数
    if (!b) {
        d = a;
        x = 1;
        y = 0;
    }
    else {
        exgcd(b, a % b, d, y, x);
        y -= x * (a / b);
    }
}
const int MAXN = 2e4 + 10;
bool notprime[MAXN];
int prime[MAXN / 10];
void getPrime() {
	memset(notprime, false, sizeof(notprime));
	notprime[0] = notprime[1] = true;
	prime[0] = 0;
	for (int i = 2; i < MAXN; i++) {
		if (!notprime[i])prime[++prime[0]] = i;
		for (int j = 1; j <= prime[0] && prime[j] < MAXN / i; j++) {
			notprime[prime[j] * i] = true;
			if (i % prime[j] == 0) break;
		}
	}
}
long long factor[2][2];
int fatCnt;
int getFactors(long long x) {
	fatCnt = 0;
	long long tmp = x;
	for (int i = 1; i < prime[0] && prime[i] <= tmp / prime[i]; i++) {
		factor[fatCnt][1] = 0;
		if (tmp % prime[i] == 0) {
			factor[fatCnt][0] = prime[i];
			while (tmp % prime[i] == 0) {
				factor[fatCnt][1]++;
				tmp /= prime[i];
			}
			fatCnt++;
		}
		if (fatCnt == 1) break;
	}
	if (tmp != 1) {
		factor[fatCnt][0] = tmp;   //存放分解的素数
		factor[fatCnt++][1] = 1;   //存放此素数出现次数
	}
	return fatCnt;   //分解的素数个数(不相同)
}
int t;
ll a, b;
int main() {
	getPrime();
    scanf("%d", &t);
    while (t--) {
        scanf("%lld%lld", &a, &b);
        ll g = gcd(a, b);
        if (g != 1) printf("%lld %lld %lld %lld\n", (a + g) / g, b / g, 1ll, b / g);
        else {
			int cnt = getFactors(b);
			if (cnt <= 1) puts("-1 -1 -1 -1");
			else {
				ll f = 1ll * powl(factor[0][0], factor[0][1]);
				ll d = b / f;
				ll temp, x, y;
				exgcd(f, d, temp, x, y);
				if(x > 0) printf("%lld %lld %lld %lld\n", a * x, d, -a * y, f);
				else printf("%lld %lld %lld %lld\n", a * y, f, -a * x, d);
			}
        }
    }
	return 0;
}

你可能感兴趣的:(数论,扩展欧几里得)