方程的解题解和扩欧的一些总结

Posted 2020pengxiyue

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了方程的解题解和扩欧的一些总结相关的知识,希望对你有一定的参考价值。

题目描述

给出一个二元一次方程ax+by=c,其中x、y是未知数,求它的正整数解的数量。

输入输出格式

输入格式:

 

第一行一个整数T,表示有T组数据。接下来T行,每行3个整数a、b、c。

 

输出格式:

 

输出T行,每行一个数,表示方程解的数量。如果正整数解的数量比65535还多输出“ZenMeZheMeDuo”。

 

题解

这个题一看就要先用扩展欧几里得求出一组x最小的整数解然后再计算出所有的解。

 

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 long long Exgcd(long long a, long long b, long long & x, long long & y)
 5     {
 6         if(b == 0)
 7             {
 8                 x = 1, y = 0;
 9                 return a;
10             }
11         int q = Exgcd(b, a % b, y, x);
12         y -= x * (a / b);
13         return q; 
14     }
15 
16 long long Get_ans_num(long long  a, long long b, long long c, long long &x, long long &y)
17     {
18         const int maxnum = 70000;
19         long long fa = 0, fb = 0;
20         if(a == 0 && b == 0)
21             {
22                 if(c == 0)    return maxnum;
23                 else return 0;
24             }
25         if(a == 0)
26             {
27                 if(c == 0)    return maxnum;
28                 if(c % b == 0 && c /b > 0)    return maxnum;
29                 return 0;
30             }
31         if(b == 0)
32             {
33                 if(c == 0)    return maxnum;
34                 if(c % a == 0 && c / a > 0)    return maxnum;
35                 return 0;
36             }
37         if(c < 0)    a = -a, b = -b, c = -c;
38         if(a < 0)    a = -a, fa = 1;
39         if(b < 0)    b = -b, fb = 1;
40         long long gcd = Exgcd(a, b, x, y);
41         if(c % gcd != 0) return 0;
42         long long t = c / gcd;
43         x = x * t, y = y * t;
44         a = a / gcd, b = b / gcd, c = t;        
45         if(fa)    a = -a, x = -x;
46         if(fb)    b = -b, y = -y;
47         if(a < 0)    a = -a, b = -b, c = -c;
48         if(a * b < 0)    return maxnum;
49         x = x % b;
50         for(;x <= 0;) x += b;
51         y = (c - a * x) / b;
52         if(y < 0)    return 0;
53         long long miny = y % a;
54         for(;miny <= 0;)    miny += a;
55         if(miny > y)    return 0;
56         return (y - miny) / a + 1;
57     }
58 
59 int main()
60 {
61     //freopen("fuction.in", "r", stdin);
62     //freopen("fuction.out", "w", stdout);
63     long long T, a, b, c, ans, x, y;
64     scanf("%lld", &T);
65     for(int i = 1; i <= T; ++ i)
66         {
67             scanf("%lld%lld%lld", &a, &b, &c);
68             ans = Get_ans_num(a, b, c, x, y);
69             if(ans <= 65535) printf("%lld
", ans);
70             else    printf("ZenMeZheMeDuo
");
71         }
72 }


关于扩展欧几里得的总结

  1. 扩欧与方程的通解

  扩展欧几里得是用于求解方程 ax + by = gcd(a,b)的解的(要求a,b非负)。对于方程ax+by=gcd(a,b),知道一组特解x0,y0我们一定能够求出它的通解:

    技术分享图片

 

  将其推广的话对于方程ax+by=c,我们首先要解的方程是ax+by=gcd(a,b)解为x0’,y0‘

  若c|gcd(a,b),则令t=c/gcd(a,b),对于等式ax0‘+by0‘=gcd(a,b)两边同时乘以t就有等式a(tx0‘)+b(ty0‘)=gcd(a,b)*t=c,所以原方程的一组解就是x0=tx0‘,y0=ty0‘,而在这种情况下,我们能够得到它们的通解:

  技术分享图片

2.在二元一次方程组整数解中的一些特殊情况(ax+by=c)

    • 若a==0且b==0,若有c==0,则有无数组解,但若c!=0则无解。
    • 当a*b>0时整数解的组数有可能是有限的。
    • 当a==0时若有c%b==0则有无数组解(x可取任意整数,y=(c/b)),当y>0时有无数组正整数解;b==0时亦然。

  3.在用扩欧解方程时,若有负数,可通过方程式变形来处理

 

以上是关于方程的解题解和扩欧的一些总结的主要内容,如果未能解决你的问题,请参考以下文章

20190722

欧几里得算法和扩欧

同余方程

方程的解

同余方程(扩欧模板)

NOIP提高组2012 同余方程