【2020年牛客暑假第三场】F题 Fraction Construction Problem

【2020年牛客暑假第三场】F题 Fraction Construction Problem

题目连接:https://ac.nowcoder.com/acm/contest/5668/Fhtml

题目描述
There are t queries.
In each query, you are given two positive integers a a and b b ( a , b 2 × 1 0 6 ) (a, b\leq2×10^6)
Please print a line consists of four positive integers c , d , e , f c,d,e,f satisfying the following constraints:java

  • c d e f = a b \frac{c}{d}-\frac{e}{f}=\frac{a}{b}
  • d < b d < b and f < b f < b
  • 1 c , e 4 × 1 0 12 1\leq c, e \leq4×10^{12}

If there are multiple solutions, you can print anyone.ios

If there are no solution, please print “-1 -1 -1 -1” in this line.web

输入描述
The first line contains one integer t t ( 1 t 1 0 5 ) (1\leq t\leq 10^5) — the number of test cases.算法

The only line of each test case contains two integers a a and b b ( a , b 2 × 1 0 6 ) (a, b\leq2×10^6) 数组

输出描述app

For each test case print four integers — c , d , e , f c,d,e,f . If there are no solution, c , d , e , f c,d,e,f should all be 1 -1 .svg

输入
3 3
4 4 1 1
1 1 6 6
37 37 111 111 this

输出
1 -1 1 -1 1 -1 1 -1
1 1 2 2 1 1 2 2
145 145 87 87 104 104 78 78 spa

思路

  • 状况一: b = = 1 b == 1 b b 是质数 无解
  • 状况二: g c d ( a , b ) ! = 1 gcd(a,b)!=1
    假设 k = g c d ( a , b ) k=gcd(a,b) 则存在一组解 ( a / k + 1 , b / k , 1 , b / k ) (a/k + 1, b/k, 1, b/k)
  • 状况三:b不是质数
    即b能够分红两个相异质因数相乘,因此先找到 d f d、f 使得 d × f = b d×f=b d f d、f 互质
    找d,f的方法:先打表3e6之内的素数,而后先找出第一个被b整除的素数,这个数就是d,而后f就是b/d(相似算数基本定理)

在d,f找到以后就开始找c和e了。

已知d*f = b,通分后可得 c × f e × d = a c×f-e×d=a (d、f、a都知道,求c、e),求解c和e,即用扩展欧几里得算法。

注意:求出c和e以后判断一下谁正谁负,毕竟d和f和b的两个相异质因数是不知道对应谁的,能够经过c和e的正负性判断。

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a,b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 1e9 + 7;
 const int maxn = 5e6 + 10;
// const double eps = 1e-6;


int prime[1005]; // 素数数组
bool is_prime[maxn]; // is_prime[i]表示i为素数
int p;

void sieve() // 返回n之内的素数个数
{
    int n = maxn;
    mem(is_prime, true);
    is_prime[0] = is_prime[1] = false;
    is_prime[2] = true;
    
    for(int i = 2;i * i <= n; i++)
    {
        if(is_prime[i])
        {
            prime[++p] = i;
            for(int j = 2 * i;j <= n; j += i)
            {
                is_prime[j] = false;
            }
        }
    }
}

ll gcd(ll a, ll b)
{
    return b == 0 ? a : gcd(b, a % b);
}

ll ex_gcd(ll a, ll b, ll &x, ll &y)
{
    ll res, t;
    if(!b)
    {
        x = 1;
        y = 0;
        return a;
    }
    res = ex_gcd(b, a % b, x, y);
    t = x;
    x = y;
    y = t - (a / b) * y;
    return res;
}

ll solve_ex_gcd(ll a, ll b, ll c, ll &x, ll &y)
{
    ll inv = ex_gcd(a, b, x, y);
    if(c % inv)
    {
        x = -1;
        y = -1;
        return -1;
    }
    x *= (c / inv);
    y *= (c / inv);
    return 0;
}

void solve()
{
    ll a, b;
    cin >> a >> b;
    ll k = gcd(a, b);
    if(k != 1)
    {
        a /= k;
        b /= k;
        cout << a + 1 << " " << b << " " << 1 << " " << b << endl;
        return ;
    }
    if(b == 1 || is_prime[b])
        cout << "-1 -1 -1 -1" << endl;
    else
    {
        ll tmp = 0, time = 0;
        ll bb = b;
        for(int i = 1;i <= p && bb != 1; i++) // 找两个素因数
        {
            if(bb % prime[i] == 0)
            {
                tmp = prime[i];
                while(bb % prime[i] == 0)
                {
                    time++;
                    bb /= prime[i];
                }
                break;
            }
        }
        if(bb == 1)
        {
            cout << "-1 -1 -1 -1" << endl;
            return ;
        }
        ll d = 1;
        for(int i = 1;i <= time; i++)
        {
            d *= tmp; // b的一个因数
        }
        ll f = bb; // b的另外一个因数
        ll c = 0, e = 0;
        solve_ex_gcd(f, d, a, c, e);
        if(c < 0 && e > 0)
        {
            cout << e << " " << f << " " << -c << " " << d << endl;
        }
        else
            cout << c << " " << d << " " << -e << " " << f << endl;
    }
}

signed main()
{
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#else
    ios::sync_with_stdio(false);
    sieve();
    int T = 1;
    cin >> T;
    while(T--)
        solve();
#endif
    return 0;
}