2020牛客暑期多校训练营(第三场)F. Fraction Construction Problem

链接

https://ac.nowcoder.com/acm/contest/5668

题意

已知 $a,b(a,b\le2\times10^6)$

求 $c,d,e,f$ 满足一下要求

  • $\frac{c}{d}-\frac{e}{f}=\frac{a}{b}$
  • $d<b,f<b$
  • $1\le c,e\le 4\times10^{12}$

思路

设$g=gcd(a,b)$

情况一:$g\ne1$

$\frac{a}{b}$ 的最简形式为 $\frac{a/g}{b/g}$,根据最简分数的唯一性可得 $d=b/g,e=b/g,c-e=a/g$,另 $e=1$,所以 $c=a/g+1$

情况二:$g=1$

  • b的不同的质因数的个数小于 $1$

    无解

    设$b=p^k$,因为 $g=1$,所以 $\frac{a}{b}$ 就是最简分数,那么 $\frac{c}{d}-\frac{e}{f}$ 的最简形式就是 $\frac{a}{b}$,又因为 $d<b,f<b$,所以 $d$ 和 $f$ 中质因数 $p$ 的个数都小于 $k$,所以不成立

  • b的不同的质因数的个数大于 $1$

    另 $d*f=b$ 且 $gcd(d,f)=1$,用扩展欧几里得算法求解 $cf-ed=a$

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include<bits/stdc++.h>
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(),(x).end()
#define PB push_back
#define MP make_pair
#define FI first
#define SE second
#define int long long
using namespace std;
typedef double DB;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<PII> VPII;
//head
const int N=2e6+5;
int m,p[N],mn[N]; //mn[i] 为 i的最小质因数
void Euler_seive(int n) { //注意筛后 mn[1]=0
for(int i=2;i<=n;i++) {
if(mn[i]==0) mn[i]=i,p[++m]=i;
for(int j=1;j<=m;j++) {
if(p[j]>mn[i]||p[j]*i>n) break;
mn[i*p[j]]=p[j];
}
}
}
int gcd(int a,int b) {return b?gcd(b,a%b):a;}
int exgcd(int a,int b,int &x,int &y) {
if(b==0) {
x=1;
y=0;
return a;
}
int ret=exgcd(b,a%b,x,y);
int z=x;
x=y;
y=z-(a/b)*y;
return ret;
}
int get(int x) {
if(mn[x]==x||x==1) return x;
int ret=1;
int t=x;
while(t%mn[x]==0) t/=mn[x],ret*=mn[x];
return ret;
}
signed main() {
Euler_seive(2000000);
int T;
scanf("%lld",&T);
while(T--) {
int a,b;
scanf("%lld%lld",&a,&b);
int c,d,f,e;
int g=gcd(a,b);
if(g!=1) printf("%lld %lld %lld %lld\n",a/g+1,b/g,1,b/g);
else {
f=get(b);
if(f==b) puts("-1 -1 -1 -1");
else {
d=b/f;
g=exgcd(f,d,c,e);
if(c<0) printf("%lld %lld %lld %lld\n",e*a,f,-c*a,d);
else printf("%lld %lld %lld %lld\n",c*a,d,-e*a,f);
}
}
}
return 0;
}