uvaoj 571 Jugs 互质数
本题只要求给出一个解,不要求最优。所给的两个罐子容量一定互质,因此必然可以倒出从0到大罐容量间的任何整数值。原理是若A,B互质,则最小公倍数为A×B,即不存在一个1 < n < B,使得nA能被B整除。令r = nA mod B(mod为取模操作),那么当n从0到B-1变化时,r可以取到0到B-1之间的任何值。
现在的问题就是用AB两个罐子相互倒水来模拟这个数学过程。设小罐容量为A,大罐容量为B。每次将A装满后倒入B中。若第m次后B已装满,A剩下的水量为r1,则有:
r1 = mA mod B
然后将B倒空,把A中剩余的r1装入B。又经过n次从把A装满倒入B的操作后B被装满,此时A剩下的水量为r2,则有:
r2 = (r1 + nA) mod B
= (mA mod B + nA) mod B
= (m+n)A mod B
由此可知,倒的方法就是每次将A中的水倒进B,但每次在做这一步之间要先检查A、B中的水量,如果A为空,就将A装满;如果B已倒满,就将B清空。最后一定可以在某个时候在B罐中得到需要的水量。
现在的问题就是用AB两个罐子相互倒水来模拟这个数学过程。设小罐容量为A,大罐容量为B。每次将A装满后倒入B中。若第m次后B已装满,A剩下的水量为r1,则有:
r1 = mA mod B
然后将B倒空,把A中剩余的r1装入B。又经过n次从把A装满倒入B的操作后B被装满,此时A剩下的水量为r2,则有:
r2 = (r1 + nA) mod B
= (mA mod B + nA) mod B
= (m+n)A mod B
由此可知,倒的方法就是每次将A中的水倒进B,但每次在做这一步之间要先检查A、B中的水量,如果A为空,就将A装满;如果B已倒满,就将B清空。最后一定可以在某个时候在B罐中得到需要的水量。
代码如下:
/*************************************************************************
> File Name: 571.cpp
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2015年01月09日 星期五 16时12分02秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
const double esp = 1e-5;
int main(int argc, char *argv[])
{
int a, b, goal;
while (scanf("%d%d%d", &a, &b, &goal) != EOF) {
int x = 0;
int y = 0;
while (y != goal) {
if (x == 0) {
x = a;
printf("fill A\n");
}
if (y == b) {
y = 0;
printf("empty B\n");
}
y += x;
x = 0;
if (y > b) {
x = y - b;
y = b;
}
printf("pour A B\n");
}
printf("success\n");
}
return 0;
}
参考:
1)http://www.cnblogs.com/devymex/archive/2010/08/04/1792288.html