codevs4290 二元一次不定方程~(三星)
2015-10-25 21:36
253 查看
题目链接——————>codevsvsvsvsvsvs
(^q^/∠)
一行 三个数,a,b,c;
一行,x y或too simple或sometimes naive
30% 0<=a,b,c<=10;
70% 0<=a,b,c<=500000000;
100% 总之我这个渣渣能过;
别的不说,直接开解~
这题显然exgcd,但是暴力for也能拿60分左右。
我们先来讨论那几个特殊情况,即无解和无正整数解的情况。
1、 a == b == 0的情况,样例1,输出“0 0”
2、a == 0 && b != 0的情况
这时原方程变成了一元一次方程,无整数解得情况就是c%b != 0的情况,因为不能整除,这时输出“too simple”,如果满足整除,再看c/a是否是正整数输出。
3、a != 0 && b == 0 同上处理~
4、a != 0 && b != 0的情况下:
开始我想直接暴力取出exgcd的答案,然后利用while循环来得到最小值,但是这样我爆了,于是弃疗了一段时间。
之后一个叫space-time的大神给我讲了一下,我才了解了方程可以这么解……
下面将具体解答:
ax + by = c;
by = (c - ax);
y = (c-ax)/b;
因为y是整数,所以(c-ax)必定整除于b,即b|(c-ax);
然后根据取模的性质:(c%b-ax%b)%b = 0;
得到同余方程:ax=c(mod b);
将x移过去得:x = c/a(mod b);
对于y,只要求得x就能求得y了,所以现在的主要目的是求得x,根据同余方程,只要求得c/a就能求得x了,这里在取模意义下的除法,可以对a求在mod b意义下的逆元,然后转化成乘法求得x即可~
这里还是有许多细节问题:
①首先对a,b,c求最大公约数,进行约分,减小爆掉的可能
②如果不存在逆元显然属于无解的情况~
嗯 处理出来逆元之后对x用公式:
注意点③:如果x < 0 || y < 0属于无正整数解情况~
如果上面所有的判断都不符合,那么这组解就是最优解了~,输出即可~。
下面附上完整代码:
2333 蒟蒻Orz各位神犇
题目描述 Description
背景:(^q^/∠)
描述:
[code]已知a,b,c, 求满足ax+by=c的整数对(x,y)中x为正整数且最小; 若此时0<=x,y,则输出x y,若此时y<0则输出“sometimes naive”(没有双引号); 若没有整数对(x,y)满足条件则输出“too simple”
输入描述 Input Description
输入一行 三个数,a,b,c;
输出描述 Output Description
输出一行,x y或too simple或sometimes naive
样例输入 Sample Input
[code]#1 0 0 0 #2 2 0 1
样例输出 Sample Output
[code]#1 0 0 #2 too simple
数据范围及提示 Data Size & Hint
数据范围30% 0<=a,b,c<=10;
70% 0<=a,b,c<=500000000;
100% 总之我这个渣渣能过;
题解:
这题我经历了几个阶段:认真做->弃疗->认真做->找大神->大神讲(space-time Orz)->AC;别的不说,直接开解~
这题显然exgcd,但是暴力for也能拿60分左右。
我们先来讨论那几个特殊情况,即无解和无正整数解的情况。
1、 a == b == 0的情况,样例1,输出“0 0”
2、a == 0 && b != 0的情况
这时原方程变成了一元一次方程,无整数解得情况就是c%b != 0的情况,因为不能整除,这时输出“too simple”,如果满足整除,再看c/a是否是正整数输出。
3、a != 0 && b == 0 同上处理~
4、a != 0 && b != 0的情况下:
开始我想直接暴力取出exgcd的答案,然后利用while循环来得到最小值,但是这样我爆了,于是弃疗了一段时间。
之后一个叫space-time的大神给我讲了一下,我才了解了方程可以这么解……
下面将具体解答:
ax + by = c;
by = (c - ax);
y = (c-ax)/b;
因为y是整数,所以(c-ax)必定整除于b,即b|(c-ax);
然后根据取模的性质:(c%b-ax%b)%b = 0;
得到同余方程:ax=c(mod b);
将x移过去得:x = c/a(mod b);
对于y,只要求得x就能求得y了,所以现在的主要目的是求得x,根据同余方程,只要求得c/a就能求得x了,这里在取模意义下的除法,可以对a求在mod b意义下的逆元,然后转化成乘法求得x即可~
这里还是有许多细节问题:
①首先对a,b,c求最大公约数,进行约分,减小爆掉的可能
②如果不存在逆元显然属于无解的情况~
嗯 处理出来逆元之后对x用公式:
[code]xx = (ny%b*c%b)%b; //ny = 逆元 yy = (c-a*xx)/b;
注意点③:如果x < 0 || y < 0属于无正整数解情况~
如果上面所有的判断都不符合,那么这组解就是最优解了~,输出即可~。
下面附上完整代码:
[code]#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll a,b,c,xx,yy; ll gcd(ll a,ll b) {return b == 0 ? a : gcd(b,a%b);}; ll exgcd(ll a,ll b,ll &x,ll &y) { if(a == 0 && b == 0) return -1; if(b == 0) {x = 1,y = 0; return a;} ll d = exgcd(b,a%b,x,y); ll t = x; x = y,y = t-a/b*y; return d; } int main() { scanf("%lld%lld%lld",&a,&b,&c); if(a == 0 && b == 0){puts("0 0"); return 0;} if(a == 0) { if(c % b) {puts("too simple"); return 0;} ll k = c / b; if(k >= 0) {printf("0 %lld\n",k); return 0;} else {puts("sometimes naive"); return 0;} } if(b == 0) { if(c % a) {puts("too simple"); return 0;} ll k = c / a; if(k >= 0) {printf("%lld 0\n",k); return 0;} else {puts("sometimes naive"); return 0;} } ll gg = gcd(a,(gcd(b,c))); if(gg > 0) {a /= gg,b /= gg,c /= gg;} ll x,y,d = exgcd(a,b,x,y); if(d != 1) {puts("too simple"); return 0;} ll ny = (x%b+b)%b; xx = (ny%b*c%b)%b; yy = (c-a*xx)/b; if(xx < 0 || yy < 0) puts("sometimes naive"); else printf("%lld %lld",xx,yy); return 0; } // 4 7 8
2333 蒟蒻Orz各位神犇
相关文章推荐
- 积累
- LDAP 认证服务可用性监测
- matlab实现RBF的相关函数
- 古罗马子串加密
- 设计原本 --- 理性模型
- 【特种兵PPT教程】如何在PPT中快速插入一条绝对水平的直线?
- android---(数据库实践)
- CentOS 6.5 中文输入法没有候选框解决
- 【字符串】变位词
- android中图片的三级cache策略(内存、文件、网络)之二:内存缓存策略 .
- 排序算法二:直接插入排序
- 程序员不要仅靠经验,不多思考
- cf 19a World Football Cup
- Foundation 之 NSDictionary和NSMutableDictionary
- 创建git私有仓库
- 第十章、国际供应源搜寻中的风险和机会
- (转)Java读带有BOM的UTF-8文件乱码原因及解决方法
- [转] Eclipse的Tomcat插件安装
- lightoj 1356 - Prime Independence 【质因子分解 奇偶构图 + HK优化】
- 第118讲:Hadoop内存需求量及Namenode内存使用详解学习笔记