牛客多校(2020第三场)F Fraction Construction Problem
题目链接:https://ac.nowcoder.com/acm/contest/5668/F
题意:
给定一个分数a/b,请构造俩个分数c/d, e/f满足 c/d - e/f = a/b,且 d < b && f < b
题解:
1. a和b不互质, 设g = gcd(a, b),则 d = f = b / g, c = a/g + 1, e = a/g;
2. a和b互质, 且b的相异质因子不超过1个, b无法符合题意分解,无解。
3. a和b互质, 且b的相异质因子超过1个, 先找到d * f = b, 且 d, f互质, 然后的到 c * f - e * d = a, 使用扩展欧几里得算法。
1 #include<iostream>
2 #include<cstring>
3 #include<algorithm>
4 #include<cmath>
5 using namespace std;
6 #define ll long long
7 const int N = 2e6 + 5;
8
9 int v[N], prime[N], num_prime[N], vis[N];
10
11 void init() {
12 memset(v, 0, sizeof(v));
13 int m = 0;
14 for (int i = 2; i <= sqrt(N); i++) {
15 if (!vis[i]) {
16 v[i] = i; //没有访问过的,最小质因子就是自己
17 for (int j = i*i; j < N; j+=i) { //寻找最小质因子是i的数
18 vis[j] = 1;
19 if (!v[j]) v[j] = i;
20 }
21 }
22 }
23
24 memset(num_prime, 0, sizeof(num_prime));
25 num_prime[1] = 1;
26 for (int i = 2; i <= N; i++) {
27 if (v[i]) {
28 num_prime[i]++;
29 int temp = i;
30 while (temp % v[i] == 0) {temp /= v[i];}
31 if (temp != 1) {
32 num_prime[i]++;
33 }
34 }
35 }
36 }
37
38 ll x, y;
39 void exgcd(ll a, ll b) {
40 if (b) {
41 exgcd(b, a%b);
42 ll temp = x;
43 x = y;
44 y = temp - a/b * y;
45 }
46 else
47 x = 1, y = 0;
48 }
49
50 ll gcd(int a, int b) {
51 return b? gcd(b, a%b): a;
52 }
53
54 int main() {
55 init();
56 int t;
57 scanf("%d", &t);
58 while (t--) {
59 int a, b;
60 scanf("%d %d", &a, &b);
61 int g = gcd(a,b);
62 if (g != 1) {
63 a = a/g;
64 b = b/g;
65 printf ("%d %d %d %d\n", a+1, b, 1, b);
66 continue;
67 }
68 if (num_prime[b] <= 1) {printf("-1 -1 -1 -1\n"); continue;}
69 ll d = 1, f = b;
70 while (f % v[b] == 0) {
71 f /= v[b];
72 d *= v[b];
73 }
74
75 exgcd(f, d);
76 y = -y;
77 while (x < 0 || y < 0) {x += d, y += f;}
78 ll c = x * a, e = y * a;
79 printf ("%lld %lld %lld %lld\n",c,d,e,f);
80 }
81 }

浙公网安备 33010602011771号