题意:给定a和b,构造 c d − e f = a b \dfrac{c}{d}-\dfrac{e}{f}=\dfrac{a}{b} dc−fe=ba 且 d , f < b d,fd,f<b
题解:
1.当ab不互质,即ab存在非1公因数时,可以构造出 a + x b − x b = a b \dfrac{a+x}{b}-\dfrac{x}{b}=\dfrac{a}{b} ba+x−bx=ba ,x任取,因为要求 d , f < b d,fd,f<b,对等式左边分子分母同除ab的gcd即可(当然其他的非1公因数也可),设g为ab的gcd,构造的等式为 a g + 1 b g − 1 b g = a b \dfrac{\dfrac{a}{g}+1}{\dfrac{b}{g}}-\dfrac{1}{\dfrac{b}{g}}=\dfrac{a}{b} gbga+1−gb1=ba
2.当ab互质,但b的互异质因子只有一个时,则无解。
证明:b的互异质因子只有一个,即 b = p k b=p^k b=pk,上式通分后得到 c f − e d d f = a b \dfrac{cf-ed}{df}=\dfrac{a}{b} dfcf−ed=ba,则 d ′ = p k 1 , f ′ = p k 2 d'=p^{k_{1}},f'=p^{k_{2}} d′=pk1,f′=pk2,那么 d , f d,f d,f一定包含因子 p s p^{s} ps, c f , e d cf,ed cf,ed也一定包含因子 p s p^{s} ps,则a一定包含因子 p s s p^{ss} pss,与ab互质矛盾
3.当ab互质,且b的互异质因子大于1个时,可令 d f = b df=b df=b,找到一组互质的 d , f d,f d,f带入上式, c f − e d = a = > f x − d y = g c d ( f , d ) ∗ a cf-ed=a =>fx-dy=gcd(f,d)*a cf−ed=a=>fx−dy=gcd(f,d)∗a,拓展欧几里得找一组可行解即可,注意找到的 x , y x,y x,y可能为负,换一下即可
当 b = 1 b=1 b=1或b为质数时,一定无解,可以用线性筛先将质数筛出来,提高效率。b的范围是2e6,我看成了1e6,没筛完,导致一直wa(自抠双目)
Code:
#include
using namespace std;
#define ll long long
#define db double
#define ull unsigned ll
#define pii pair
#define pdd pair
#define pll pair
#define mem(a, b) memset(a, b, sizeof(a));
#define lowbit(x) (x & -x)
#define lrt nl, mid, rt << 1
#define rrt mid + 1, nr, rt << 1 | 1
template <typename T>
inline void read(T& t) {
t = 0;
int f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
t = t * 10 + ch - '0';
ch = getchar();
}
t *= f;
}
const int dx[] = {0, 1, 0, -1};
const int dy[] = {1, 0, -1, 0};
const ll Inf = 0x7f7f7f7f7f7f7f7f;
const int inf = 0x7f7f7f7f;
const db eps = 1e-5;
const db Pi = acos(-1);
const int maxn = 2e6 + 10;
int cnt;
bool is_prime[maxn];
int primes[maxn];
void Primes(int n) {
memset(is_prime, true, sizeof(is_prime));
is_prime[1] = 0;
for (int i = 2; i <= n; i++) {
if (is_prime[i])
primes[++cnt] = i;
for (int j = 1; j <= cnt && i * primes[j] <= n; j++) {
is_prime[i * primes[j]] = 0;
if (i % primes[j] == 0)
break;
}
}
}
void exgcd(ll a, ll b, ll& x, ll& y) {
if (!b) {
y = 0, x = 1;
return;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
}
int main(void) {
Primes(2e6);
int T;
read(T);
while (T--) {
ll a, b, c, d, e, f, k;
read(a), read(b);
if (__gcd(a, b) != 1) {
ll k = __gcd(a, b);
printf("%lld %lld 1 %lld\n", a / k + 1, b / k, b / k);
continue;
}
if (b == 1 || is_prime[b]) {
printf("-1 -1 -1 -1\n");
continue;
}
ll tmp = b, op = 1;
for (int i = 1; primes[i] * primes[i] <= tmp; i++) {
if (tmp % primes[i] == 0) {
while (tmp % primes[i] == 0)
tmp /= primes[i], op *= primes[i];
break;
}
}
if (tmp == 1) {
printf("-1 -1 -1 -1\n");
continue;
}
d = tmp, f = op;
ll x, y;
exgcd(f, d, x, y);
c = x * a, e = y * a;
if (c < 0 && e > 0)
printf("%lld %lld %lld %lld\n", e, f, -c, d);
else
printf("%lld %lld %lld %lld\n", c, d, -e, f);
}
return 0;
}