题意: 给定
,求出满足
的任意一组
。
数据范围:
,
,且
题解: 通分得到: ,那么自然会考虑到分子分母对应相等解决。
- 当
,令
,此时
这时候 ,故直接令 ,
那么可以构造出 -
,那么此时需要分解
成两个互质的部分
,且
均不为
,否则判
那么预处理 内的质数,并处理出每个数的最小质因子,就可以 分解 了。
分解成功后 即可。
这里有个技巧,由于是 进行 ,我们可以变成 ,然后得到 后再取反即可。注意最后的答案必须是正数,且扩大 倍,这也是 最大范围的原因。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6 + 10;int pri[N], cnt;
int Mipri[N];
bool st[N];
void xs(int n) {st[0] = st[1] = true;Mipri[1] = 1;for(int i = 2; i <= n; i++) {if(!st[i]) pri[cnt++] = i, Mipri[i] = i;for(int j = 0; j < cnt && 1ll * i * pri[j] <= n; j++) {Mipri[i * pri[j]] = pri[j];st[i * pri[j]] = true;if(i % pri[j] == 0) break;}}
}int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);
}void exgcd(ll a, ll b, ll &x, ll &y) {if(!b) {x = 1, y = 0; return ;}exgcd(b, a % b, y, x);y -= a / b * x;
}int main()
{xs(N - 1);int T; scanf("%d", &T);while(T--) {int a, b;scanf("%d%d", &a, &b);int g = gcd(a, b);if(g > 1) {int f = 1, e = 1, d = b / g, c = (a + b) / g;printf("%d %d %d %d\n", c, d, e, f);continue;}ll f = 1, d = b, p = Mipri[b];while(p > 1 && d % p == 0) d /= p, f *= p;if(d == 1) {puts("-1 -1 -1 -1");continue;}ll c, e;exgcd(d, f, e, c);e = -e;if(e <= 0 || c <= 0) {ll e1 = (e % f + f) % f;ll c1 = (c % d + d) % d;ll cnt = max(0ll, max((e1 - e) / f, (c1 - c) / d));e += f * cnt, c += d * cnt;}e *= a, c *= a;printf("%lld %lld %lld %lld\n", c, d, e, f);}return 0;
}