题目链接: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 ", a+1, b, 1, b); 66 continue; 67 } 68 if (num_prime[b] <= 1) {printf("-1 -1 -1 -1 "); 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 ",c,d,e,f); 80 } 81 }