题目大意:就是给你两个数
a
,
b
a,b
a,b叫你求满足下面三个条件的
c
,
d
,
e
,
f
c,d,e,f
c,d,e,f
1.
c
d
−
e
f
=
a
b
1.{c\over d}-{e\over f}={a\over b}
1.dc−fe=ba
2.
d
<
b
&
&
f
<
b
2.d<b\&\&f<b
2.d<b&&f<b
3.
c
,
e
∈
[
1
,
4
e
12
]
3.c,e\in[1,4e12]
3.c,e∈[1,4e12]
我们先将第一个式子通分
c
∗
f
−
e
∗
d
d
∗
f
=
a
b
{c*f-e*d\over d*f}={a\over b}
d∗fc∗f−e∗d=ba
1.如果
g
c
d
(
a
,
b
)
>
1
,
那
么
a
和
b
可
以
进
一
步
化
简
:
a
1
=
a
/
g
c
d
(
a
,
b
)
,
b
1
=
b
/
g
c
d
(
a
,
b
)
;
那
么
我
们
可
以
直
接
令
d
=
b
1
,
f
=
1
,
e
=
1
,
c
=
a
1
+
b
1
;
gcd(a,b)>1,那么a和b可以进一步化简:a_1=a/gcd(a,b),b1=b/gcd(a,b);那么我们可以直接令d=b_1,f=1,e=1,c=a_1+b_1;
gcd(a,b)>1,那么a和b可以进一步化简:a1=a/gcd(a,b),b1=b/gcd(a,b);那么我们可以直接令d=b1,f=1,e=1,c=a1+b1;
2.如果
g
c
d
(
a
,
b
)
=
1
,
我
们
就
不
能
像
上
面
那
样
赋
值
了
因
为
题
目
的
第
二
个
限
制
条
件
。
gcd(a,b)=1,我们就不能像上面那样赋值了因为题目的第二个限制条件。
gcd(a,b)=1,我们就不能像上面那样赋值了因为题目的第二个限制条件。因为
a
/
b
a/b
a/b是最简的形式那么等式两边应该是对应相等的那么
b
=
d
∗
f
,
a
=
c
∗
f
−
e
∗
d
b=d*f,a=c*f-e*d
b=d∗f,a=c∗f−e∗d,那么我们将
b
b
b分解成
d
∗
f
d*f
d∗f再去讨论
a
=
c
∗
f
−
e
∗
d
a=c*f-e*d
a=c∗f−e∗d,这不就是扩展欧几里得算法吗?
3:如何分解
b
b
b:通过分数的形式可以知道
d
和
f
d和f
d和f是互质的,如果不互质通分后得式子上下相消分母就会变得比
b
b
b小了
4.如何将b分解成两个互的数:我们可以运用欧拉筛的性质将每个数最小的质因数筛出来如何不断调整
ll d = 1, f = b;
int k = isnp[b];
while(f % k == 0 && k != 1)
{
f /= k;
d *= k;
}
a
=
c
∗
f
−
e
∗
d
a=c*f-e*d
a=c∗f−e∗d这个式子是一元方程值域为
[
−
无
穷
到
+
无
穷
]
[-无穷到+无穷]
[−无穷到+无穷]我们只要随便一对d,f带入求c,e都一定有解
5.注意扩展欧几里的通解的处理,以及扩展欧几里得求出来的通解是
c
∗
f
−
e
∗
d
=
g
c
d
(
d
,
f
)
=
1
c*f -e*d=gcd(d,f)=1
c∗f−e∗d=gcd(d,f)=1的解答案记得要扩大
a
a
a倍
#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define next Next
#define count Count
#define pb push_back
#define f first
#define s second
using namespace std;
const int N = 2e6+10, mod = 1e9 + 7;
const double eps = 1e-10;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args)
{
read(first);
read(args...);
}
int T, n;
int prime[N], cnt;
int isnp[N];
bool vis[N];
void init()
{
isnp[1] = 1;
for(int i = 2; i < N; ++ i)
{
if(!vis[i])
{
isnp[i] = i;
prime[cnt ++] = i;
}
for(int j = 0; j < cnt && prime[j] * i < N; ++ j)
{
vis[i * prime[j]] = true;
isnp[i * prime[j]] = prime[j];
if(i % prime[j] == 0) break;
}
}
}
ll exgcd(ll a,ll b,ll &x,ll &y)//扩展欧几里得算法
{
if(b==0)
{
x=1;y=0;
return a; //到达递归边界开始向上一层返回
}
ll r=exgcd(b,a%b,x,y);
ll temp=y; //把x y变成上一层的
y=x-(a/b)*y;
x=temp;
return r; //得到a b的最大公因数
}
int main()
{
init();
read(T);
while(T --)
{
ll a,b;
read(a,b);
ll G = __gcd(a,b);
if(G > 1)
cout << (a + b) / G << " " << b / G << " 1 1" << endl;
else
{
ll d = 1, f = b;
int k = isnp[b];
while(f % k == 0 && k != 1)
{
f /= k;
d *= k;
}
if(d == b && f == 1) cout << "-1 -1 -1 -1" << endl;
else
{
ll c,e;
exgcd(f,d,c,e);
e = -e;
while(c <= 0 || e <= 0)
{
c += d;
e += f;
}
e *= a, c *= a;
cout << c << " " << d << " " << e << " " << f << endl;
}
}
}
return 0;
}