剑指ACM_1,原题+python代码——Feli的生日礼物、取石子游戏、钱币兑换问题

来源:互联网 发布:java方法重载意义 编辑:程序博客网 时间:2024/05/17 23:33

前言
ACM号称是世界上最聪明人之间的比赛,其奖牌的含金量是非常高的,是程序员求职时的利器,同时,在笔试的时候,很多公司的笔试就是ACM当中的一些简单题目,这里,我会陆续分享和讲解一些ACM当中的题目、代码,希望能够帮到大家

一、Feli的生日礼物

Feli的生日是11月1日,于是Feli请来Kitty一起过生日。Kitty带来了最新款的“Kitty猫”玩具准备送给Feli,不过她说,这份礼物可不是白送的。Feli要帮她一个忙,才能够得到心仪已久的玩具。 Kitty说,“Kitty猫”玩具已经卖出了n!个,n<=10^100 ,Kitty想知道确切的数字,而不是无聊的“一个数加个感叹号”。 Feli听了大吃一惊。要知道,算出n!是一个无比艰巨的任务。Feli告诉Kitty,就算Feli算出n!,Kitty也看不下去,因为当n=20时,计算机的长整型已经存不下了(Kitty只能接受1-9之间的数字)。于是Kitty说,你只要告诉我n!最后一位非0的数就可以了
————————————————————————————————————————————
Input:每行一个n,直到输入数据结束
————————————————————————————————————————————
Output:对应输入的n,每行输出一个答案
————————————————————————————————————————————
Sample Input:
1101

Sample Output:
4
————————————————————————————————————————————
解题思路:这一题起点很高,乍看上去很难,但其实是比较简单的,因为它只要求知道最后一位非零的数就可以了,所以,在求阶乘时,我们只需要将两个取两个数的最后一位非零数进行运算就可以了
代码:

'''1.Input a certain amount of Nfor every N,return the last number which is not 0 of the N's factorial '''def present_Kitty():    def get_N():        num = []        num.append(input())        while num[-1] != '':            num.append(input())        return num    def get_last(N):        strnum,j = str(N),-1        while strnum[j] == '0':            j -= 1        return int(strnum[j])    def calculate(N):        res,i = 1,2        intn = int(N)        if intn < 2:            return 1        else:            while i <= intn:                res = get_last(res) * get_last(i)                i += 1            return get_last(res)    N,i = get_N(),0    while i < len(N)-1:        print(calculate(N[i]))        i += 1

测试代码:

present_Kitty()

输入与输出:

这里写图片描述

二、取石子游戏

有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。
————————————————————————————————————————————
Input:输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于1,000,000,000。
————————————————————————————————————————————
Output:输出对应也有若干行,每行包含一个数字1或0,如果最后你是胜者,则为1,反之,则为0
————————————————————————————————————————————
Sample Input
2 1
8 4
4 7

Sample Output
0
1
0
————————————————————————————————————————————
解题思路:这题需要我们仔细的观察题目,该题要求博弈的双方都采取最优策略,同时给出胜负结果,很容易想到,输入分为两类,一类是先取的人赢,一类是先取的人输,在双方都取最优策略的情况下,不存在可能赢可能输的情况,输赢只取决于初始时石堆
在确定这一条件下,我们只需要确定先走的人什么时候输就可以,由于两个石堆不分身份,像(1,2)(2,1)这种情况,在程序内部统一设置成(1,2)升序,只需要考虑一个就好
这里列出一些情况:

(1,2)(2,)(3,5)(4,7)(5,)(6,10)(8,13)(9,15)(10,)(11,18)

其实,知道威佐夫博弈的人应该看出来了,这其实是威佐夫博弈的实例,不知道的话也只能靠序列推导了,这里给出(x,y)的推导公式

x = int(1.618*k)y = int(2.618*k)k = 123...

根据上面的分析可以给出
代码:

'''2.There are two heaps of stones, any number, could be different. The start of the game by two people take turns to take stone.The game rules:There are two different methodsFirst can in arbitrary takes a heap as many stones; Second can take the same number of stones in the two heaps.The end is the winner take all the stones.We know the number of the two initial heaps of stones nowif you begin first, assuming that both sides take the best strategy,output that you are the winner or loser?'''def take_Stones():    def set_order(a):        if a[0] > a[1]:            b = (a[1],a[0])        else:            b = (a[0],a[1])        return b    def get_input():        num = []        a = input().split()        a = (int(a[0]),int(a[1]))        a = set_order(a)        num.append(a)        while num[-1] != '':            a = input()            if a != '':                a = a.split()                a = (int(a[0]),int(a[1]))                set_order(a)                num.append(a)            else:                break        return num    num = get_input()    res,i = [],0    while i < len(num):        if int((num[i][0]//1.618+1)*1.618) != num[i][0]:            res.append(1)        else:            if num[i][1] == int(2.618*(num[i][0]//1.618+1)):                res.append(0)            else:                res.append(1)        i += 1    print(res,end = '\n')

测试代码:

take_Stones()

输入与输出:
这里写图片描述

三、钱币兑换问题

在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法。请你编程序计算出共有多少种兑法
————————————————————————————————————————————
Input:每行只有一个正整数N,N小于32768
————————————————————————————————————————————
Output
对应每个输入,输出兑换方法数
————————————————————————————————————————————
Sample Input
2934
12553

Sample Output
718831
13137761
————————————————————————————————————————————
解题思路:这里十分简单,但需要注意代码的效率,不要使用嵌套循环
代码:

'''3.In a country, there are  only 1 cent, 2 cents,3 cents coins Now we need to use them to break down N cents,there are many methodsPlease program to calculate the  number of methods '''import datetimedef break_Money(N):    begin_time = datetime.datetime.now()    num = [0]    Two_Cent = 0    while N-2*Two_Cent >= 0:        num[0] += 1        Two_Cent += 1    i = 1    k = int(N/3)+1    while i < k:        if (N - 3*(i-1))%2 == 0:            num.append(num[i-1]-2)        else:            num.append(num[i-1]-1)        i += 1    i = 0    sum = 0    k2 = len(num)    while i < k2:        sum += num[i]        i += 1    end_time = datetime.datetime.now()    print(begin_time,end_time)    print('cost:  ' + str(end_time - begin_time))    return sum

测试代码:

print(break_Money(2934))print(break_Money(12553))print(break_Money(32767))

测试结果:
这里写图片描述

原创粉丝点击