zoukankan      html  css  js  c++  java
  • 模拟7题解 T1方程的解

    方程的解

    [扩展欧几里德]

    首先进行特判,两个小时基本想到了,除了a!=0,b==0,a*c<0这种情况

    其次就是一般情况:

    首先exgcd求出ax+by=GCD(a,b)的一组任意解

    然后两边同乘(c/GCD)使x,y成为原方程的一组任意解,

    剩下讲解见代码

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #define int long long
     5 using namespace std;
     6 const int mx=65535;
     7 int read()
     8 {
     9     int f=1,x=0;char ch=getchar();
    10     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    11     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    12     return f*x;
    13 }
    14 int exgcd(int a,int b,int &x,int &y)
    15 {
    16     if(!b){x=1,y=0;return a;}
    17     int d=exgcd(b,a%b,x,y);
    18     int tmp=x;x=y;y=tmp-(a/b)*y;
    19     return d;
    20 }
    21 int a,b,c;
    22 int  ans;
    23 void work()
    24 {
    25     //特判出现0的情况
    26     if(a==0&&b==0&&c==0){ans=mx+10;return;}
    27     if(a==0&&b==0&&c!=0){ans=0;return;}
    28     if(a==0||b==0)
    29     {
    30         if(c==0)   {ans=0;return;}
    31         if(a==0)  swap(a,b);
    32         if(a*c<0){ans=0;return;}
    33         a=abs(a),c=abs(c);
    34         if(c%a==0){ans=mx+10;return;}
    35         else      {ans=0;return;}
    36     }
    37     //特判ab与c异号
    38     if(a>0&&b>0&&c<=0){ans=0;return;}
    39     if(a<0&&b<0&&c>=0){ans=0;return;}
    40     //特判a,b异号
    41     int x,y;
    42     int d=exgcd(a,b,x,y);
    43     if(c%d){ans=0;return;}
    44     if(a*b<0){ans=mx+10;return;}//注意这两行代码顺序,反例3 -3 5:应先进行上一步判定c%d!=0
    45     //abc同号时,可以先处理a==b==1和a+b==c两种特殊情况,拿到部分分
    46     if(a<0) a=-a,b=-b,c=-c,d=-d;    
    47 /*    if(a==1&&b==1)
    48     {
    49         if(c>=2)    ans=c-1;
    50         else ans=0;
    51         return;
    52     }
    53     if(a+b==c)   {ans=1;return;}*/
    54     //再处理一般情况
    55     ans=0;
    56     x*=(c/d),y*=(c/d);//x,y成为原方程的一组特解
    57     a/=d,b/=d,c/=d;//系数约分后使GCD(a,b)==1
    58     x=(x%b+b)%b;//使得x成为符合条件的最小正整数,,通过+b避免负数
    59     if(x==0)  x+=b;//注意x为0的特殊情况
    60     int ymax=(c-a*x)/b;//x最小时求出y的最大值
    61     y=(y%a+a)%a;
    62     if(y==0) y+=a;//同理求y的最小值
    63     ans=(ymax-y)/a+1;//对于ymin->ymax之间的y,对应的x可能不是整数,所以/a成为x是整数的个数,因为包括两端,所以+1
    64     return;
    65 }
    66 signed main()
    67 {
    68     int T=read();
    69     while(T--)
    70     {
    71         a=read(),b=read(),c=read();
    72         work();
    73         if(ans>mx)  puts("ZenMeZheMeDuo");
    74         else printf("%lld
    ",ans);
    75     }
    76 }
    View Code
    愿你在迷茫时,记起自己的珍贵。
  • 相关阅读:
    开学测试感想
    动手动脑1(00JAVA语言基础)
    9.29 java web注释方式以及servlet映射
    三十道随机算法
    9.30 servlet学习
    C#验证控件的使用方法
    SqlHelper详解
    C#字符串的几种常用方法
    存储过程事务处理
    js url编码
  • 原文地址:https://www.cnblogs.com/casun547/p/11228307.html
Copyright © 2011-2022 走看看