F.Fraction Construction Problem(exgcd&数论)

F.Fraction Construction Problem(exgcd&数论)

题意:给定正整数 a , b a,b ,构造出正整数 c , d , e , f c,d,e,f ,满足 c d e f = a b , ( d , f < b ) \dfrac{c}{d}-\dfrac{e}{f}=\dfrac{a}{b},(d,f<b)

思路: e x g c d + exgcd+ 数论。


p 1 : p 1: a , b a,b 不互质时,即 g c d ( a , b ) > 1 gcd(a,b)>1

我们可以构造这样一个式子: a + b b 1 = a b \dfrac{a+b}{b}-1=\dfrac{a}{b}

b = b g , a = a g b'=\dfrac{b}{g},a'=\dfrac{a}{g}

a + b b 1 = a b = a b \dfrac{a+b}{b}-1=\dfrac{a}{b}=\dfrac{a'}{b'}

a + b g = a + b g b g \dfrac{a+b}{g}=\dfrac{\dfrac{a+b}{g}}{\dfrac{b}{g}}

c = a + b g , d = b g , e = f = 1 c=\dfrac{a+b}{g},d=\dfrac{b}{g},e=f=1

这样能满足 1 d , f < b 1\leq d,f<b


p 2 : a , b p2:a,b 互质且 b b 质因数的种类只有一个。

这种情况是无解的,因为 d , f < b d,f<b ,所以 d , f d,f 的分解质因数 p k p_k 的个数都小于 b b p k p_k 个数,所以左边 d f df 通分后,分母不可能等于 b b


p 3 : p3: a , b a,b 互质且 b b 质因数种类不只一个。

显然我们可以构造出互质的两个数 d , f d,f 满足 d × f = b d\times f=b

这样有 c f d e d f = a b \dfrac{cf-de}{df}=\dfrac{a}{b}

c f d e = a cf-de=a ,在 f , d , a f,d,a 已知下求 c , d c,d ,这显然是扩展欧几里得。

且肯定有整数解,因为 d , f d,f 互质,说明 g c d ( d , f ) = 1 , 1 a gcd(d,f)=1,1|a 则必定有整数解。

接下来套板子就可以了 ,注意是求正整数解,所以当 c c 为负数时要将其变为正整数。

可能有人会问 c c 为正数时,能不能保证 e e 也是正数呢,当然可以。

因为 f c 1 d e 1 = 1 fc_1-de_1=1 ,显然 c 1 c_1 为正数,因为 f , d f,d 为正数,显然 e 1 e_1 为正数。

即: c = c 1 × a , e = e 1 × a c=c_1\times a,e=e_1\times a 都为正数。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int a,b,p[N],vis[N],ss[N];
void pre(){
    int n=2e6,cnt=0;
    ss[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i])
            p[cnt++]=i,ss[i]=i;
    for(int j=0;j<cnt&&i*p[j]<=n;j++){
        vis[i*p[j]]=1,ss[i*p[j]]=p[j];
        if(i%p[j]==0) break;
    }
     }
}
template<class T>
void exgcd(T a,T b,T &x,T &y){
    if(!b){
        x=1,y=0;
        return;
    }
    exgcd(b,a%b,y,x);
    y-=(a/b)*x;
}
int main(){
    int t;
    pre();
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&a,&b);
        int g=__gcd(a,b);
        if(g>1){
        printf("%d %d 1 1\n",(a+b)/g,b/g);  //不互质.
        continue;
        }
        ll f=b,d=1;
        while(b>1&&f%ss[b]==0) f/=ss[b],d*=ss[b];
        if(f==b||f==1) puts("-1 -1 -1 -1");
        else {
        ll c,e;
        exgcd(f,d,c,e);
        if(c<0)
        c=(c%d+d)%d,e=(1-f*c)/d;
        c*=a,e*=a;
        printf("%lld %lld %lld %lld\n",c,d,-e,f);
    }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107436473
今日推荐