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

题目描述

给出一个二元一次方程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\n", ans);
70             else    printf("ZenMeZheMeDuo\n");
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.在用扩欧解方程时,若有负数,可通过方程式变形来处理

原文地址:https://www.cnblogs.com/2020pengxiyue/p/9314237.html

时间: 2024-10-18 17:41:37

方程的解题解和扩欧的一些总结的相关文章

9.10 第一题 方程的解 题解

这道题当时感觉是一道几乎纯考扩展欧几里得的题,然而板子忘了--于是乎这道题被我放在第二个打. 不得不说出题人相当良心,给了大把的暴力分前20分就是c-1,20~40暴力枚举,40~60输出1.白送的60分就到手了. 然而难得是后40分,我们可以先通过扩展欧几里得先求出x最小整数解,然后首先,自己本身就无解的方程输出0就好了,其次,如果a,b中有一个为零那么就是无限解如果都为0就看c,如果异号就是无限解等等等等特判,然后就没什么了,注意要开long long,细节真心坑,而且特判的顺序也极其重要.

『扩欧简单运用』

扩展欧几里得算法 顾名思义,扩欧就是扩展欧几里得算法,那么我们先来简单地回顾一下这个经典数论算法. 对于形如\(ax+by=c\)的不定方程,扩展欧几里得算法可以在\(O(5log_{10}\min\{a,b\})\)的时间内找到该方程的一组特解,或辅助\(gcd\)判断该方程无解. 对于扩欧的详细讲解,可见『扩展欧几里得算法 Extended Euclid』. 那么我们注意到一个问题,扩展欧几里得算法求的只是一组特解.事实上,我们可以根据如下公式得到不定方程的通解: \[ \begin{cas

扩展欧几里德算法.....哦,扩欧

首先推荐两篇比较好的博客 http://blog.csdn.net/lincifer/article/details/49391175 (然后下面便是一个蒟蒻的总结QAQ) 扩展欧几里德算法 基本算法: 对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 ax + by = gcd(a, b) = d. 证明: 设 a > b. 1. 显然当 b = 0,gcd (a,b) = a 时, x = 1,y = 0: 2. ab != 0

方程的解

总之这题如果静下心来仔细想,拿个80分并不难 问题:扩欧只会板子,并未理解,扩欧解出来的是一组解而已,并没有最值等的特殊性. ax+by=c必须在c能整除gcd(a,b)的情况下,此时会有n多组解,设d=gcd(a,b);x=(c/d)*x0+k*(b/d),y=(c/d)*x0-k*(a/d); 这题还是值得好好看看,因为特判情况可以搞到许多分.包括数据范围的特判,解的个数的特判. 1 #include<cstdio> 2 #include<cstring> 3 #include

Codeforces Round #305 (Div. 2)C---Mike and Frog(扩欧+乱搞)

Mike has a frog and a flower. His frog is named Xaniar and his flower is named Abol. Initially(at time 0), height of Xaniar is h1 and height of Abol is h2. Each second, Mike waters Abol and Xaniar. So, if height of Xaniar is h1 and height of Abol is

用c语言求ax^2+bx+c=0方程的解

用c语言求ax^2+bx+c=0方程的解.#include <stdio.h>#include <math.h>#define m 0.000001int main(){     float a,b,c,x,x2,n,q,p;     scanf ("%f%f%f",&a,&b,&c);     n=b*b-4*a*c;     if ((a<m)&&(a>-m))     {         x=(-c)/b

欧几里得算法和扩欧

7.31.2018修改 欧几里得算法 概念 在数学中,辗转相除法,又称欧几里得算法(英语:Euclidean algorithm),是求最大公约数的算法. 辗转相除法基于如下原理:两个整数的最大公约数等于其中较小的数和两数的差的最大公约数. 两个数的最大公约数通常写成GCD(a, b),或者简写成(a, b) (引自wikipidia) 实现 用伪代码描述 //gcd(x,y) //(x>=y>0) while x!=0&&y!=0 z=x x=x mod y y=z 最后非零

欧几里得(辗转相除gcd)、扩欧(exgcd)、中国剩余定理(crt)、扩展中国剩余定理(excrt)简要介绍

1.欧几里得算法(辗转相除法) 直接上gcd和lcm代码. 1 int gcd(int x,int y){ 2 return y==0?x:gcd(y,x%y); 3 } 1 int lcm(int x,int y){ 2 return x*y/gcd(x,y); 3 } 2.扩欧:exgcd:对于a,b,一定存在整数对(x,y)使ax+by=gcd(a,b)=d ,且a,b互质时,d=1. x,y可递归地求得. 我懒得改返回值类型了 1 long long exgcd(long long a,

codevs3732==洛谷 解方程P2312 解方程

P2312 解方程 195通过 1.6K提交 题目提供者该用户不存在 标签数论(数学相关)高精2014NOIp提高组 难度提高+/省选- 提交该题 讨论 题解 记录 题目描述 已知多项式方程: a0+a1x+a2x^2+..+anx^n=0 求这个方程在[1, m ] 内的整数解(n 和m 均为正整数) 输入输出格式 输入格式: 输入文件名为equation .in. 输入共n + 2 行. 第一行包含2 个整数n .m ,每两个整数之间用一个空格隔开. 接下来的n+1 行每行包含一个整数,依次