• 方程的解 扩展欧几里德


      题面加密

      首先看到这道题就能想到用exgcd,但是怎么用,我们知道这种方程一有就是一堆解,那么这个题的限制就是解的个数,我们考虑如果把方程移项化简就能得到$y=frac{c}{b}-frac{a}{b}*x$,这时候就用到义务教育的知识了,当a,b异号那么一定同增,如果exgcd有解,一定是无限组,直接判掉。我们考虑ab同号,那么我们可以得到一定是过第一象限的递减直线,我们对方程做如下操作$a(x-b)+b(y+a)=c$,显然也是成立的,此时ab都可以化成正号,那么x减小则y增加,我们可以将x对b取模得到y的最大解,再将y对a取模得到y最小解,然后y的变换一定是一个等差数列,公差为a,则y的范围可以求,命题得解(装X)。

      然后特判一下就A了,快读记得打负号


      

    #include<iostream>
    #include<cstdio>
    #define ll long long
    using namespace std;
    ll rd()
    {
        ll s=0,w=1;
        char cc=getchar();
        while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();}
        while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar();
        return s*w;
    }
    ll exgcd(ll a,ll b,ll &x,ll &y,ll c)
    {
        if(b==0){x=c/a;y=0;return a;}
        ll d=exgcd(b,a%b,y,x,c);
        y-=a/b*x;
        return d;
    }
    int main()
    {
    //    freopen("data.in","r",stdin);
        //freopen("data.ans","w",stdout);
        ll T=rd(),a,b,c,x,y,g,ans;
        while(T--)
        {
            a=rd(),b=rd(),c=rd();
            //cout<<a<<" "<<b<<endl;
            if(!a&&!b)
            {
                if(!c)printf("ZenMeZheMeDuo
    ");
                else printf("0
    ");
                continue;
            }
            if(a<0&&b<0) a=-a,b=-b,c=-c;
            g=exgcd(a,b,x,y,c);
            if(c%g){puts("0");continue;}
            if(a==0)
            {
                if((b<=0&&c>=0)||(b>=0&&c<=0))printf("0
    ");
                else printf("ZenMeZheMeDuo
    ");
                continue;
            }
            if(b==0)
            {
                if((a<=0&&c>=0)||(a>=0&&c<=0))printf("0
    ");
                else printf("ZenMeZheMeDuo
    ");
                continue;
            }
            if(a*b<0)
            {
                printf("ZenMeZheMeDuo
    ");
                continue;
            }
            if(a<0&&b<0)a=-a,b=-b,c=-c;
            a/=g;b/=g;c/=g;x%=b;
            while(x<=0)x+=b;
            y=(c-a*x)/b;
            ll ymin=y%a;while(ymin<=0)ymin+=a;
            if(ymin>y)ans=0;
            else ans=(y-ymin)/a+1;
            if(ans>65535)printf("ZenMeZheMeDuo
    ");
            else printf("%lld
    ",ans);
        }
    }
    /*
    g++ 6.cpp -o 6
    ./6
    4
    1 -1 3
    1 1 65536
    1 1 65537
    2 3 24
    */
    View Code
    Zeit und Raum trennen dich und mich.时空将你我分开。
  • 相关阅读:
    linux每天一小步---grep命令详解
    linux每天一小步---xargs命令详解
    linux每天一小步---find命令详解
    linux每天一小步---tail命令详解
    linux每天一小步---head命令详解
    linux每天一小步---alias命令详解
    linux每天一小步---cat命令详解
    linux每天一小步---mv命令详解
    第十四周总结
    第十三周总结
  • 原文地址:https://www.cnblogs.com/starsing/p/11235533.html
Copyright © 2020-2023  润新知