标签:sicily
Time Limit: 1 secs, Memory Limit: 256 MB
The first and only line of input contains two positive integers, N and M (1 ≤ N, M ≤ 100), the number of sausages and tasters, respectively.
The first and only line of output must contain the required minimum number of cuts.
样例1: 2 6 样例2: 3 4 样例3: 6 2
样例1: 4 样例2: 3 样例3: 0
COCI 2013.9/2014年每周一赛第一场
非常值得令人思考的一道题,参考了大神的资料才得以做出:
分析:
看上面的图已经显而易见了,可以把人看成一段段线,香肠也是如此,然后,最少刀数的办法就是尽量使人与人之间的端点和香肠之间的断点(不是用刀切的)重合;
那么,在人的那条线上的没有重合的点数就是最少的刀数。
怎么求不重合的点数呢?首先m个人有m + 1个端点,但是两端的端点是不用考虑的,也就是只用考虑m - 1个端点。
设每个人的长度为y,每条香肠的长度为x,那么首先有x * n = m * y;
设i个人后与j条香肠后会有一个端点重合,即i * y = j * x;
那么在人里面的个数就是(m * y)/ (i * y) ,在香肠里就是(x * n)/(j * x);
分子分母都是相同的,说明在人里面和在香肠里面的个数是相同的;
消去上式中的x和y,得:m / i = n / j;
设它们等于k;
那么k显然是m和n的公共的约数;
而为了使人和香肠之间的断点尽可能的多,我们就要使i和j尽可能的短,那么由m / k = i以及n / k = j知道,k就要尽可能的大;
所以k就是m,n的最大公约数;
那么再由(m * y)/ (i * y) = k 以及(x * n)/(j * x)= k可知,不包括两端的重合的点数就是gcd(n,m)- 1;
那么切的最少刀数,也就是不重合的考虑的点数m - 1 减去考虑的重合的点数 (gcd(n, m) - 1);
代码:
#include <stdio.h> int gcd(int a, int b) { if (b == 0) return a; else return gcd(b, a % b); } int main() { int n, m; scanf("%d%d", &n, &m); printf("%d\n", m - 1 - (gcd(n, m) - 1)); return 0; }
Sicily 10330. Cutting Sausages
标签:sicily
原文地址:http://blog.csdn.net/u012925008/article/details/44738831