P5656 【模板】二元一次不定方程 (exgcd)
【模板】二元一次不定方程 (exgcd)
题目描述
给定不定方程
若该方程无整数解,输出
若该方程有整数解,且有正整数解,则输出其正整数解的数量,所有正整数解中
若方程有整数解,但没有正整数解,你需要输出所有整数解中
正整数解即为
整数解即为
输入格式
第一行一个正整数
接下来
输出格式
若该行对应的询问无整数解,一个数字
若该行对应的询问有整数解但无正整数解,包含
否则包含
读入输出量较大,注意使用较快的读入输出方式
样例 #1
样例输入 #1
7 2 11 100 3 18 6 192 608 17 19 2 60817 11 45 14 19 19 810 98 76 5432
样例输出 #1
4 6 2 39 8 2 1 -1 1600 1 18 3199 30399 34 3 -1 2 12 7 50 56
提示
【数据范围】
对于
part 1
则
其他的就正常开始用exgcd做就行,详情 [NOIP2012 提高组] 同余方程
part 2
方程可以写成
而这其中的
所以
part 3(注意)
1 开long long
2 part 2中的k的左右范围在开始时是不可以取到等于的,所以防止出现smin和smax刚好被整除的情况出现要处理一下,因为分母与分子在不被整除的情况下相差一定大于等于1,所以加小于等于1的都数都行
3 x与y在刚出exgcd时是在
其他相关可见我参考的博客
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; long long t , a , b , c , g , temp; long long x , y , xmax , xmin , ymax , ymin , solution; long long smin , smax;//记得是long long inline long long read() { long long x = 0 , f = 1 ; char ch = getchar(); while ( ch < '0' || ch > '9' ) { if ( ch == '-' ) f *= -1; ch = getchar(); } while ( ch >= '0' && ch <= '9' ) { x = ( x << 1 ) + ( x << 3 ) + ( ch - '0' ); ch = getchar(); } return x * f; }//快读 void exgcd( long long a_ ,long long b_ ) { if ( b_ == 0 ){ x = 1; y = 0; return; } exgcd( b_ , a_ % b_ ); temp = x; x = y; y = temp - ( a_ / b_ ) * y; return; } int main() { t = read(); while ( t -- ) { x = 0 , y = 0; a = read() , b = read() , c = read(); g = __gcd( a , b ); if ( c % g != 0 ) { puts("-1"); continue; } a /= g , b /= g , c /= g; //缩小精度 防止出现b过大的情况 exgcd( a , b ); //因为a(x1+kb)+b(y1-ka) = c = a*x1+kab+b*y1-kab =a*x1+b*y1 //所以通解形式是x = x1 + kb 和 y = y1 - ka //这里得到 x > 0 和 y > 0 //x1 + kb > 0 则 k > - ( x1 / b ) //y1 - ka > 0 则 k < ( y1 / a ) //因为原式子不可取等 //所以在取等的时候前面要加上1后面减1防止出现刚好simn和smax可以整除的情况 x *= c; y *= c; smin = ceil ( ( (double) -x + 1.0 ) / (double)b);//这里注意除的是b smax = floor ( ( (double) y * 1.0 - 1.0 ) / (double)a);//这里注意除的是a smin = floor ( smin ); smax = ceil ( smax ); solution = smax - smin + 1; xmin = x + smin * b; ymax = (c - a * xmin) / b; ymin = y - smax * a; xmax = (c - b * ymin) / a; if ( smin > smax ) printf ( "%lld %lld\n" , xmin , ymin ); else printf( "%lld %lld %lld %lld %lld\n" , solution, xmin , ymin , xmax , ymax ); } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战