URAL 1430
来源:互联网 发布:js验证11位手机号码 编辑:程序博客网 时间:2024/06/05 01:05
题目大意:给出a,b,N,找出自然数x,y满足:N-(a*x+b*y)的值最小,如果有多组解是,输出任意一组。
Time Limit:500MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
数据规模:1<=a,b,N<=2^9。
理论基础:扩展欧几里得算法:在URAL 1204中已经做了详细介绍这里不再累赘。
裴蜀定理:如果对任意两个整数a,b,关于未知数x和y的线性丢番图方程(称为裴蜀等式):a*x+b*y=c有解的充要条件是:gcd(a,b)整除c。
线性丢番图方程解的个数:如果裴蜀等式有一组解x0,y0,那么:x=x0-t*b,y=y0+t*a也是原方程的解,所以裴蜀等式有解时,那么必有无数组解。
题目分析:确实是一个简单的最优化的问题,可以有两种思路:
思路1:在保证a*x+b*y=m有自然数解的情形下,使得m最大(m<=n),求出解。这个用扩展欧几里得算法即可解决,判断有无解,如果有,求解(先求出一组解x0,y0,因为a,b大于0,所以解必然一正一负,若x0为负,则令t=(int)floor((float)x0/b),算出y0+t*a如果为负表示无自然数解,y0为负时亦然),枚举出的第一个数即为所求,当然这不会超时,因为加了两次验证每次验证的复杂度都是O(1),会筛掉很多值。而且保证了解的最优性。当然,前面再加上一些下述的情况就万无一失了。
思路二:枚举x,y这种方式比较直接,易懂。如何枚举呢?
首先,不难想到,如果a==1或者b==1那么结果就为:n 0 or 0 n,如果:n%a==0||n%b==0,那么结果就为:n/a 0||n/b 0。
然后考虑一般情况,首先,如果a>b,t=b,b=a,a=t。这样我们就可以定出枚举的范围了,bor=min(n/a,b),这不难想到如果x大于n/a,b小的一项时,那么:假设:bor=n/a,那当:x>n/a时a*x>n不符合要求,如果:bor=b时,那么当x>b时我们完全可以将x拆为(i+b),那么i又变得比b小了,而且i已经枚举过了,更新最小值,记录当时的x即为解咯。讲解完毕。
代码如下:
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#define maa (1<<31)#define mii ((1<<31)-1)#define forlec(i, a, b) for(int i##_b = (b), i = (a); i <= i##_b; ++i)template<class T> inline bool updateMin(T& a, T b) { return a>b? a=b, true: false; }int a,b,n,x,flag=0,Min=mii;int main(){ scanf("%d%d%d",&a,&b,&n); if(a==1||b==1) { a==1?printf("%d 0\n",n):printf("0 %d\n",n); exit(0); } if(a==b) { printf("%d 0\n",n/a); exit(0); } if(a<b) { int temp=a; a=b; b=temp; flag=1; } int t=min(n/a,b); forlec(i,0,t) { if(updateMin(Min,(n-a*i)%b))x=i; } if(!flag)printf("%d %d\n",x,(n-a*x)/b); else printf("%d %d\n",(n-a*x)/b,x);return 0;}
我自然采用的是第二种解法啦,通俗易懂。。。
参考文献:
http://zh.wikipedia.org/wiki/%E8%B2%9D%E7%A5%96%E7%AD%89%E5%BC%8F
by:Jsun_moon http://blog.csdn.net/jsun_moon
- URAL 1430
- URAL
- 【ural】
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- [leetcode刷题系列]Unique Binary Search Trees
- Android应用开发之(管理好你的网络操作)
- 尚学堂面试整理题目
- Merge Two Sorted Lists
- 有这样一段程序,求解???
- URAL 1430
- [leetcode刷题系列]Unique Binary Search Trees II
- unity3d_场景间数据传递
- HDU4576 Robot
- Extjs中面板布局的应用
- Two Sum
- Linux c 进程的理解
- [leetcode刷题系列]Binary Tree Inorder Traversal
- 装win7