[51nod1479]小Y的数论题——构造+exgcd

题目大意:

小Y喜欢研究数论,并且喜欢提一些奇怪的问题。
这天他找了三个两两互质的数a, b, c,以及另一个数m, 现在他希望找到三个(0, m)范围内的整数x, y, z,使得
(xa+yb)Mod m=(zc)Mod m ( x a + y b ) M o d   m = ( z c ) M o d   m

思路:

这题竟然是一个构造题。
考虑构造使得式子化为 2k+2k=2k+1 2 k + 2 k = 2 k + 1 的形式,也就是 2xab+2xab=2yc 2 x a b + 2 x a b = 2 y c xab+1=yc x a b + 1 = y c ,然后用拓展欧几里得解出即可。
但是但是发现这一题在模的意义下答案可能会是0,也就是当m为 2t 2 t 时。
不妨特殊处理,若a,b,c中有大于1的数,就可以让它等于 m/2 m / 2 ,然后就变成0了。

#include<bits/stdc++.h>

#define REP(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;

using namespace std;

void File(){
    freopen("51nod1479.in","r",stdin);
    freopen("51nod1479.out","w",stdout);
}

int T;
ll mod,a,b,c,x,y;

ll exgcd(ll m,ll n){
    if(!n){x=1;y=0;return m;}
    ll g=exgcd(n,m%n),tmp=x;
    x=y; y=tmp-m/n*y;
    return g;
}

ll qpow(ll base,ll cnt){
    ll ret=1; base%=mod;
    while(cnt){
        if(cnt&1)ret=ret*base%mod;
        base=base*base%mod;
        cnt>>=1;
    }
    return ret;
}

void calc(){
    ll g=exgcd(a*b,-c);
    x=x*(-g); y=y*(-g);
    x=(x%c+c)%c; if(!x)x=c;
    y=(ll)((1+(__int128)x*a*b)/c);
    if(y<=0){
        ll d=ceil((-y*1.0)/(a*b));
        x=x+d*c; y=y+d*a*b;
        if(!y)x=x+c,y=y+a*b;
    }
    //x*a*b-y*c==-1 ? cout<<"Yes"<<endl : cout<<"No"<<endl;
    printf("%lld %lld %lld\n",qpow(2,x*b),qpow(2,x*a),qpow(2,y));
    //(qpow(qpow(2,x*b),a)+qpow(qpow(2,x*a),b))%mod==(qpow(qpow(2,y),c))%mod ? : cout<<"fuck"<<endl;
}

int main(){
    File();
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld%lld%lld",&mod,&a,&b,&c);
        ll fuck=mod;
        while(fuck%2==0)fuck/=2;
        if(fuck==1){
            if(a>1)printf("%lld %lld %lld\n",mod/2,1ll,1ll);
            else if(b>1)printf("%lld %lld %lld\n",1ll,mod/2,1ll);
            else if(c>1)printf("%lld %lld %lld\n",mod/2,mod/2,mod/2);
            else printf("%lld %lld %lld\n",1ll,1ll,2ll);
        }
        else calc();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值