牛客多校(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 }

猜你喜欢

转载自blog.csdn.net/Mrwei_418/article/details/108163304