目录:
题目描述
做题过程
别人的思路
综合感悟
1.题目描述:
在一个环形跑道上,等距离放置着 N 个小球,小球按照顺时针方向从起点开始依次编号为 1 到 N ,在最短时间内取走放在跑道上尽可能多小球的选手获胜。举办方要求每个选手只能按照顺时针方向,跳过 M-1 个号码取后走下一个小球。如当 N=5 、 M=3 时,小明能够取走所有的小球,取走的顺序依次为 1->4->2->5->3 。当 N=6 、 M=2 时,小明只能取走 3 个小球 1->3->5 。小明想知道在一场比赛中他最多能取走多少小球?
样例输入
3
5 3
6 2
10 6
样例输出
Case #1: 5
Case #2: 3
Case #3: 5
2.做题过程
最开始我把数字都分布在一个圆圈上分析,但是这样的方式非常混乱。画了好久,就是找不到规律。之后我想到了数字信号里的圆周序列,把一个短一点的例子循环写成一条直线。从1开始每隔2个球就取一个,标了好几个数,发现了规律:
等到余数再到1的时候,就是你能取到最多的球的时候。但是我又发现,这样用for循环写的话,时间复杂度O(n),肯定会超时的。
之后脑子都想炸了,不过我还是利用已有的程序编一些数,找到了关键的规律:m,n的关系如果是互质的,那就全部都能取到,如果不是互质的,通过最大公约数来化成最简的分式。这样就变成互质的了,当然这时候取到的球就是这个新的n了。
源码:
def gcd(a, b): if b == 0: return a return gcd(b, a % b) g = int(input()) c = [] for i in range(g): a = input().split() n = int(a[0]) m = int(a[1]) # 化简 gcd1=gcd(m,n) m = int(m/gcd1) n = int(n/gcd1) if n%m==0: x=int(n/m) else: x=n c.append(x) for i, iii in enumerate(c): print("Case #%d:" % (i+1), iii)
3. 别人的思路:
看了一圈,果然还是那句话:错误的答案千变忘化,正确的答案万里归一。4. 综合感悟:
做题的时候,要多角度。也要将问题展开,联系自己已有的经验知识。有的时候超时问题可以解决,实在不好解决也可以利用特例来找到答案的内在规律,从而逆向发觉解决方法。另外,这道题和公约数有关,可见,我们学过的一些基础算法有时候也是解决实际问题的关键。