方程的解(exgcd模板)

题面在考试反思中。

题解:

  这题其实只是个板子题,但考试时忘记了,又不会推导,于是凉凉。。。

  借这道题回顾一下$ exgcd $的各种特判:

  我习惯将方程$ ax+by=c $看成一次函数$ y=-\frac{a}{b}x+\frac{c}{b} $

  而在此之前我们要特判b是否为0,再根据一次函数的性质来判断。

  $ a,b,c $都为0时,无数组解。

  $ a,b $为0且$ c $不为0时,无解

  $ b=0 $时,若$ a*c<0 $,无正整数解。

        若$ c\%a=0 $,无数组解。

  $b$不为0时,若$ a=0 $时,同$b$。

        若$ a*b<0 $时,判断是否有无穷解,若否则为无正整数解。

        若$ a*b>0 $时,分三种情况:

            $ c=0 $时,无正整数解。

            $ c*b<0 $时,无正整数解。

            $ c*b>0 $时,需我们进行求解。

  而求解时我们不需枚举每个解,只需算出最大解及最小解即可,

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<vector>
 6 #include<algorithm>
 7 using namespace std;
 8 #define R register
 9 #define ll long long
10 inline ll read(){
11     ll aa=0;R int bb=1;char cc=getchar();
12     while(cc<‘0‘||cc>‘9‘)
13         {if(cc==‘-‘)bb=-1;cc=getchar();}
14     while(cc>=‘0‘&&cc<=‘9‘)
15         {aa=(aa<<1)+(aa<<3)+(cc^48);cc=getchar();}
16     return aa*bb;
17 }
18 const int lim=65535;
19 ll exgcd(ll a,ll b,ll &x,ll &y)
20 {
21     if(!b){x=1;y=0;return a;}
22     ll d=exgcd(b,a%b,x,y);
23     ll z=x;x=y;y=z-y*(a/b);
24     return d;
25 }
26 ll T,a,b,c;//6
27 inline bool solve(ll &x,ll &y)
28 {
29     ll gcd=exgcd(a,b,x,y);
30     if(c%gcd)return 0;
31     ll t=c/gcd;
32     x*=t;y*=t;
33     if(a*x+b*y!=c)return 0;
34     t=b/gcd;
35     if(t<0)t=-t;
36     while(x<0)x+=t;
37     x%=t;
38     if(!x)x+=t;
39     a/=gcd;b/=gcd;c/=gcd;//4
40     return 1;
41 }
42 inline bool work()
43 {
44     if((!a)&&(!b)&&(!c)){
45         puts("ZenMeZheMeDuo");
46         return 0;
47     }
48     if(a==0&&b==0){
49         puts("0");return 0;
50     }
51     if(!b){
52         if(c*a<0) puts("0");
53         else if(c%a==0) puts("ZenMeZheMeDuo");//5
54         else puts("0");
55         return 0;
56     }
57     if(!a){
58         if(b*c<0) puts("0");
59         else if(c%b==0) puts("ZenMeZheMeDuo");
60         else puts("0");
61         return 0;
62     }
63     if(a*b>0&&(b*c<0||!c)){ puts("0");return 0; }
64     if(a<0&&b<0){a=-a;b=-b;c=-c;}
65     return 1;
66 }
67 int main()
68 {
69     T=read();
70     while(T--){
71         a=read();b=read();c=read();
72         if(!work())continue;//特判
73         ll xi,yi,yj,ans=0;
74         if(!solve(xi,yi)){
75             puts("0");continue;
76         }
77         else{
78             if(a*b<0){//2
79                 puts("ZenMeZheMeDuo");
80                 continue;
81             }
82             if(a+b==c){ puts("1");continue; }
83             if(a==b&&a==1){
84                 c-=1;
85                 if(c>lim) puts("ZenMeZheMeDuo");
86                 else printf("%lld\n",c);
87                 continue;
88             }
89             yi=(c-a*xi)/b;
90             yj=yi%a;
91             if(yj<=0)yj+=a;
92             if(yj>yi){ puts("0");continue; }
93             ans=(yi-yj)/a+1;//3
94             if(ans>lim)puts("ZenMeZheMeDuo");
95             else printf("%lld\n",ans);
96         }
97     }
98     return 0;
99 }

龟速1022ms代码

原文地址:https://www.cnblogs.com/toot-wjh/p/11235593.html

时间: 2024-11-01 22:27:49

方程的解(exgcd模板)的相关文章

用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

9.10 第一题 方程的解 题解

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

欧几里德扩展方程 详解

作用: 欧几里德扩展方程是用来求解二元一次线性方程的.ax+by=c (a.b.c为已知数) 对于给定方程: ax+by=c,令g=gcd(a,b) 因为a是g的倍数,b也是g的倍数,所以令a=m*g , b=n*g,则: ax+by=g(m*x+n*y)=c 所得的结果c必然是g的倍数. 当且仅当mx+ny=1时,右边有最小值.而此时mn必定是互质的. 所以我们经常求的最小整数解就是求方程ax+by=gcd(a,b)的解. 解方程步骤: 对于方程 ax+by=gcd(a,b) 由欧几里德算法

方程有解习题

\(\fbox{例1}\)(2017?蚌埠模拟) 已知函数\(f(x)=lnx-x^3\)与\(g(x)=x^3-ax\)的图像上存在关于\(x\)轴的对称点,则\(a\)的取值范围为[ ] A.\((-\infty,e)\) \(\hspace{2cm}\) B.\((-\infty,e]\) \(\hspace{2cm}\) C. \((-\infty,-\cfrac{1}{e})\) \(\hspace{2cm}\) D. \((-\infty,-\cfrac{1}{e}]\) 分析:函数

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

题目描述 给出一个二元一次方程ax+by=c,其中x.y是未知数,求它的正整数解的数量. 输入输出格式 输入格式: 第一行一个整数T,表示有T组数据.接下来T行,每行3个整数a.b.c. 输出格式: 输出T行,每行一个数,表示方程解的数量.如果正整数解的数量比65535还多输出"ZenMeZheMeDuo". 题解 这个题一看就要先用扩展欧几里得求出一组x最小的整数解然后再计算出所有的解. 代码 1 #include<bits/stdc++.h> 2 using names

算法笔记--sg函数详解及其模板

sg函数大神详解:http://blog.csdn.net/luomingjun12315/article/details/45555495 模板: int f[N],SG[N]; bool S[M]; void getSG(int n) { memset(SG,0,sizeof(SG)); for(int i=1;i<=n;i++) { memset(S,false,sizeof(S)); for(int j=1;f[j]<=i&&j<M;j++) { S[SG[i-f

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 行每行包含一个整数,依次

BZOJ 3129 [Sdoi2013]方程 不定方程解的个数+组合数取模

题意:链接 方法:不定方程解的个数+组合数取模 解析: 先看n1与n2的部分的限制. 对于后半部分的限制来说,我们直接减去An1+i?1就可以转化一下求正整数解. 但是前半部分呢? 跟上一道猴子那个很像. 所以我们容斥搞就行了. 但是这道题好像不好写的地方不在这? 这题TMD不就是礼物吗! 大组合数取模如何取? 请参见我<BZOJ 礼物>的题解. 另外吐槽题干 明明是X1+X2+-+Xn=m 并不是小于等于 代码: #include <cstdio> #include <cs

C++ 二分法求解方程的解

二分法是一种求解方程近似根的方法.对于一个函数 f(x)f(x),使用二分法求 f(x)f(x) 近似解的时候,我们先设定一个迭代区间(在这个题目上,我们之后给出了的两个初值决定的区间 [-20,20][?20,20]),区间两端自变量 xx 的值对应的 f(x)f(x) 值是异号的,之后我们会计算出两端 xx 的中点位置 x'x′ 所对应的 f(x')f(x′) ,然后更新我们的迭代区间,确保对应的迭代区间的两端 xx 的值对应的 f(x)f(x) 值还会是异号的. 重复这个过程直到我们某一次