绕圆圈取球球

目录:

题目描述

做题过程

别人的思路

综合感悟

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. 综合感悟:

做题的时候,要多角度。也要将问题展开,联系自己已有的经验知识。有的时候超时问题可以解决,实在不好解决也可以利用特例来找到答案的内在规律,从而逆向发觉解决方法。另外,这道题和公约数有关,可见,我们学过的一些基础算法有时候也是解决实际问题的关键。


猜你喜欢

转载自blog.csdn.net/tommy1295/article/details/80717462