F.Fraction Construction Problem(exgcd&数论)

F.Fraction Construction Problem(exgcd&数论)

题意:给定正整数 a , b a,b a,b,构造出正整数 c , d , e , f 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,fdcfe=ba,(d,f<b)

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


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

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

b ′ = b g , a ′ = a g b'=\dfrac{b}{g},a'=\dfrac{a}{g} b=gb,a=ga

a + b b − 1 = a b = a ′ b ′ \dfrac{a+b}{b}-1=\dfrac{a}{b}=\dfrac{a'}{b'} ba+b1=ba=ba

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

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

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


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

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


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

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

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

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

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

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

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

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

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

#include
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
#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;
}

你可能感兴趣的:(exgcd,欧几里得,数论)