这题就是个公式,代码极简单。但我想,真正明白这题原理的人并不多。很多人只是随便网上一搜,找到公式a了就行,其实这样对自己几乎没有提高。

鉴于网上关于这题的解题报告中几乎没有讲解原理的,我就多说几句,也不是严格的证明,给大家分享一下。

题目是说有p人或q人吃蛋糕,需要提前把蛋糕切好而能同时满足这两种情况,使蛋糕的块数最少。为了方便表述,不妨设p < q

首先,记p和q的最小公倍数为m,则把蛋糕平均切成m块,一定是能满足条件的,但这不是最优解,暂记为解法①。

我们的工作就是把解法①的这m块中的一些尽可能合并起来(也就是之前不切开),使块数尽可能少。那么怎么合并呢?

第一个能肯定的是,每一块最大为1/q,否则当来的人数是q时就不行了。而最小呢,就是1/m。所以解法②可以这样:先切出p份1/q大小的块,剩下的部分全切成1/m大小的,这样显然也是能满足要求的。

比如p = 2, q = 3,那么就切成1/3, 1/3, 1/6, 1/6。这个例子这恰好是最优解,但并不总是所有情况都这样。

比如p = 6, q = 10,最优应该切成1/10, 1/10, 1/10, 1/10, 1/10, 1/10, 1/15, 1/15, 1/15, 1/15, 1/30, 1/30, 1/30, 1/30

而p = 24, q = 60的最优解应该是1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/60, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120, 1/120

聪明的人应该已经看出来了,其实就是继续把后面的1/m的小块合并,这些小块越来越小,最后最小的都是1/m大小的。而中间大小的块的数量怎么确定呢?

比如p = 6, q = 10时,1/15块的数量应该是4而不是6,因为如果数量是6,仅仅能满足当人数为6的情况(这时每人吃一块1/10的,加一块1/15的),但当人数为10时,这些1/15的小块无法组成1/10的大块。所以必须预留一些更小的块出来。这时,1/15的块只要保留(q-p)=4块即可。剩下的情况就是递归处理,也就是说,当切出6个1/10的块后,接下来的问题等价于处理p = 10 - 6 = 4, q = 6的情况,只是这时剩下的蛋糕只是原来的4/10而已。

如果p < q/2时成立,比如当p = 24, q = 60时,切出24个1/60的块后,应该继续切出24个1/60的块,然后再考虑1/120的小块。

这个刚好就是辗转相除法求最大公约数的过程。具体的原理大家再细细品味。

下面是代码:

/*
* Author : ben
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <functional>
#include <numeric>
#include <cctype>
using namespace std; int gcd(int a, int b) {
int r;
while (b) {
r = a % b;
a = b;
b = r;
}
return a;
} int main() {
int p, q;
while (scanf("%d%d", &p, &q) == ) {
printf("%d\n", p + q - gcd(p, q));
}
return ;
}

hdu1722 bjfu1258 辗转相除法的更多相关文章

  1. C语言辗转相除法求2个数的最小公约数

    辗转相除法最大的用途就是用来求两个数的最大公约数. 用(a,b)来表示a和b的最大公约数. 有定理: 已知a,b,c为正整数,若a除以b余c,则(a,b)=(b,c). (证明过程请参考其它资料) 例 ...

  2. 辗转相除法求最大公约数,非goto

    #include<iostream> using namespace std; //不推荐用goto,当然用它更快 //辗转相除法求两数的最大公约数 int gcd(long int a, ...

  3. C实现辗转相除法求两个数的最大公约数

    什么是辗转相除法? 辗转相除法(又名欧几里德算法),它主要用于求两个正整数的最大公约数.是已知的最古老的算法. 用辗转相除法求132和72的最大公约数的步骤: 132 / 72 = 1 ... 60 ...

  4. C++中用辗转相除法求两个数的最大公约数和最小公倍数

    两个数的最大公约数:不能大于两个数中的最小值,算法口诀:小的给大的,余数给小的,整除返回小的,即最大公约数,(res=max%min)==0?  max=min,min=res return min; ...

  5. 九度OJ 1056--最大公约数 1439--Least Common Multiple 【辗转相除法】

    题目地址:http://ac.jobdu.com/problem.php?pid=1056 题目描述: 输入两个正整数,求其最大公约数. 输入: 测试数据有多组,每组输入两个正整数. 输出: 对于每组 ...

  6. 辗转相除法_欧几里得算法_java的实现(求最大公约数)

    辗转相除法,又被称为欧几里德(Euclidean)算法, 是求最大公约数的算法. 当然也可以求最小公倍数. 算法描述 两个数a,b的最大公约数记为GCD(a,b).a,b的最大公约数是两个数的公共素因 ...

  7. L - 辗转相除法(第二季水)

    Description The least common multiple (LCM) of a set of positive integers is the smallest positive i ...

  8. poj1580---欧几里得算法(辗转相除法)

    #include<stdio.h> #include<string.h> #include<string.h> ],str2[]; int len; int cal ...

  9. 辗转相除法求H.C.F小结

    辗转相除法 大纲: 问题 原理 反思 1.     问题 一个试题,请完成以下填空 下列程序是利用辗转相除法求H.C.F(最大公约数) include <stdio.h> int main ...

随机推荐

  1. [2-sat]HDOJ3622 Bomb Game

    题意:给n对炸弹,每对炸弹选其中一个爆炸. 每个炸弹爆炸的半径相同 圆不能相交, 求最大半径 2-sat简介 二分半径, 枚举n*2个炸弹 若i炸弹与j炸弹的距离小于半径*2 则建边 比如  第一对炸 ...

  2. MySQL 卸载 --Mac

    pkill mysql sudo rm /usr/local/mysql sudo rm -rf /usr/local/mysql* sudo rm -rf /Library/StartupItems ...

  3. csh与bash比较

    csh与bash比较:一.csh的while循环控制结构及if then:#!/bin/csh -fwhile ($#argv >= 1)  if ("$1" == &quo ...

  4. JodaTime初体验

    前段时间用JDK自带的Calendar类来处理日期,需要获取年.季,月,星期的起始日期,被折腾得要死要活.看了这篇文章 http://www.blogbus.com/dreamhead-logs/22 ...

  5. cas单点登出

    由于项目需求要实现单点登出需要在网上找了N久终于实现单点登出. 使用cas-server-core-3.3.3.jar(CAS Server 3.3.3) 使用cas-client-core-3.1. ...

  6. AjaxUpLoad.js使用实现文件上传

    AjaxUpLoad.js的使用实现无刷新文件上传,如图. 图1 文件上传前 图2 文件上传后 1.创建页面并编写HTML [html] view plaincopy   上传文档: <div  ...

  7. "hadoop namenode -format"命令的作用和影响的文件

    在hadoop部署好了之后是不能马上应用的,而是对配置的文件系统进行格式化.这里的文件系统,在物理上还未存在,或者用网络磁盘来描述更加合适:还有格式化,并不是传统意义上的磁盘清理,而是一些清除与准备工 ...

  8. [Codeforces670A]Holidays(数学,构造)

    题目链接:http://codeforces.com/contest/670/problem/A 题意:给n天,问这n天最少和最多有多少个休息日,不用区分平闰年. 这题写几个例子,YY一下就构造出来解 ...

  9. Android Studio修改包名和applicationId的方法

    背景: 如果新做的项目跟以前做的某一个项目十分相似,那么一个简单的方法就是把原来项目拷贝一份,然后修改代码,但是这样包名还是原来项目的包名,还有如果想在同一台手机上同时安装新做的app和原来的app会 ...

  10. Android wakelock机制

      Wake Lock是一种锁的机制, 只要有人拿着这个锁,系统就无法进入休眠,可以被用户态程序和内核获得. 这个锁可以是有超时的或者是没有超时的,超时的锁会在时间过去以后自动解锁. 如果没有锁了或者 ...