zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校第三场F-Fraction Construction Problem-分数构造题(拓展欧几里得)

    题目大意:给你一个$a$,$b$表示$frac{a}{b}$,问你能否构造一个$frac{c}{d}-frac{e}{f}=frac{a}{b}$,如果能请输出c,d,e,f。否则输出-1 -1 -1 -1.要求$b>d,b>f,1<=c,e<=4e14$。

    emmm,有三种情况:

    第一种是分子分母不是最简,那么也就是说a,b存在一个公因子,同时也说明了b不是一个质数。那么我们可以直接构造$frac{a}{b}=frac{a+x}{b}-frac{x}{b}$,然后我们对分子分母同除以a,b的一个公因子,我们设为g,那么就会有$frac{a}{b}=frac{frac{a+x}{g}}{frac{b}{g}}-frac{frac{x}{g}}{frac{b}{g}}$,那么由于x是可以任意取的,那么我们为了方便,可以直接将其设为g,那么会得到$frac{a}{b}=frac{frac{a}{g}+1}{frac{b}{g}}-frac{1}{frac{b}{g}}$

    第二种情况,分子分母最简了,但分母的不相同的质因子不超过一个,那么无解。如果分母不相同的质因子不超过一个,那么也就是说$b$可以表示为$p^k$,那么$frac{c}{d}-frac{e}{f}=frac{a}{p^k}$,最后化简的时候一定有$d'=p^{k_1},f'=p^{k_2}$,那么$d,f$一定包含因子$p^{s}$那么对于$cf,de$也一定包含因子$p^{ss}$,也就是说他们一定有公因子$p^m$。这就和分子分母最简相互矛盾了

    第三种情况,分子分母最简了,但分母的不相同的质因子超过一个。那么一定有$df=b,gcd(d,f)=1$。那么我们只需要找到符合条件的$d,f$,然后带入到上面的式子就是$cf-ed=a$,那么可以看成$fx-dy=gcd(f,d)*a$。。。。这似乎就是拓展欧几里得了解决的问题了,拓展欧几里得不过关的话我也挺绝望的QAQ。。。

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int mac=2e6+10;
    
    int min_prim[mac],prim_num[mac];
    int vis[mac];
    
    void init()
    {
        int m=sqrt(mac);
        for (int i=2; i<m; i++){
            if (!vis[i]){
                min_prim[i]=i;
                for (int j=i*i; j<mac; j+=i){
                    vis[j]=1;
                    if (!min_prim[j]) min_prim[j]=i;//找到每个数的最小质因子
                }
            }
        }
        for (int i=1; i<mac; i++){
            if (!vis[i]) continue;
            prim_num[i]++;
            int x=i;
            while (x%min_prim[i]==0) x/=min_prim[i];
            if (x!=1) prim_num[i]++;//判断是否有两个互异的质因子 
        }
    }
    
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
        if (!b) {
            x=1; y=0;
            return a;
        }
        ll d=exgcd(b,a%b,y,x);
        y-=a/b*x;
        return d;
    }
    
    int main(int argc, char const *argv[])
    {
        int t;
        init();
        scanf ("%d",&t);
        while (t--){
            int a,b;
            scanf ("%d%d",&a,&b);
            int g=__gcd(a,b);
            if (g!=1) {
                printf("%d %d %d %d
    ",a/g+1,b/g,1,b/g);
                continue;
            }
            if (prim_num[b]<=1) {printf("-1 -1 -1 -1
    "); continue;}
            ll d=1,f=b;
            while (f%min_prim[b]==0) {
                f/=min_prim[b];
                d*=min_prim[b];
            }
            ll c,e;
            exgcd(f,d,c,e);
            e=-e;
            while (e<0 || c<0) e+=f,c+=d;
            printf ("%lld %lld %lld %lld
    ",1LL*c*a,d,1LL*e*a,f);
        }
        return 0;
    }
    路漫漫兮
  • 相关阅读:
    linux学习之路(2)
    Cocos.js
    BOM常用对象
    display取值和应用
    DOM
    cursor属性
    visibilty属性
    打开新连接的方式
    JQuery
    js的创建对象
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13339092.html
Copyright © 2011-2022 走看看