HNUCM-2022年秋季学期《算法分析与设计》练习8

目录

问题 A: X星数列

问题 B: X星计数

问题 C: 鸡兔共笼

问题 D: 与7相关的数

问题 E: 买房

问题 F: 大整数乘法

问题 G: 和费马开个玩笑

问题 H: 大还是小?


问题 A: X星数列

题目描述:

爱冒险的X星人在一艘海底沉船上发现了一串神秘数列,这个数列的前8项如下:
5, 8, 18, 34, 70, 138, 278, 554
X星人对这串数列产生了浓厚的兴趣,他希望你能够帮他发现这个神秘数列中所蕴含的规律,并且编写一个程序输出该数列前N项的和。
当输入一个正整数N时,请输出这个神秘数列前N项的和。
输入:

单组输入,每组输入一个正整数N(N<=20)。

输出:

输出一个正整数,对应这个数列前N项的和。

思路:不难发现,从第三项开始,f(n) = f(n - 1) + 2 * f(n - 2),属于斐波那契数列的变种。

nums = [5, 8, 18, 34, 70, 138, 278, 554]
n = int(input())
while n > len(nums):
    nums.append(nums[-1] + 2 * nums[-2])
print(sum(nums[:n]))

问题 B: X星计数

题目描述:

热爱数学的X星人又发现了一个有趣的游戏,游戏名叫做:1的个数。
具体游戏规则为:给定一个十进制正整数,计算对应的二进制整数中有多少个1。

输入:

多组输入。

第一行输入一个整数T(1<=T<=100),表示总共有T组数据。

接下来T行,每行一个十进制正整数n,其中1<=n<=1e^9。

输出:

对于每一组输入,输出十进制正整数对应的二进制整数中包含的1的个数。

思路:利用进制转换的思路,判断每一位即可。又因为是二进制,统计1的个数,所以直接加上转换后的数字即可。

def fun(x: int):
    res = 0
    while x > 0:
        res, x = res + x % 2, x // 2
    return res


t = int(input())
while t > 0:
    t -= 1
    try:
        n = int(input())
        print(fun(n))
    except:
        break

问题 C: 鸡兔共笼

题目描述:

一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。
已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物。

输入:

每组测试数据占1行,每行一个正整数a (a < 32768)。

输出:

输出包含n行,每行对应一个输入,包含两个正整数,第一个是最少的动物数,第二个是最多的动物数,两个正整数用一个空格分开。
如果没有满足要求的答案,则输出两个0。

思路:简单的数学题,如果输入不能整除2说明无解;如果输入全是鸡的脚数,动物数量最多,稍微注意一下,输入不难整除4的情况。

t = int(input())
while t > 0:
    t -= 1
    try:
        n = int(input())
        if n % 2 != 0:
            Max, Min = 0, 0
        else:
            Max, Min = n // 2, n // 4 + (n % 4) // 2
        print(Min, Max)
    except:
        break

问题 D: 与7相关的数

题目描述:

一个正整数,如果它能被7整除,或者它的十进制表示法中某个位数上的数字为7, 则称其为与7相关的数。
现求所有小于等于n(n<100)的与7无关的正整数的平方和。

输入:

案例可能有多组。对于每个测试案例输入为一行,正整数n,(n<100)。

输出:

对于每个测试案例输出一行,输出小于等于n的与7无关的正整数的平方和。

思路:利用一个额外的数组存储判断过的结果,也可以不用,因为数据量不大。

nums = [0] * 101
while True:
    try:
        n = int(input())
        for i in range(1, 101):
            if nums[i] != 0 or i % 7 == 0 or '7' in str(i):
                continue
            else:
                nums[i] = i ** 2
        print(sum(nums[:n + 1]))
    except:
        break

问题 E: 买房

题目描述:

某程序员开始工作,年薪N万,他希望在中关村公馆买一套60平米的房子,现在价格是200万。
假设房子价格以每年百分之K增长,并且该程序员未来年薪不变,且不吃不喝,不用交税。
每年所得N万全都积攒起来,问第几年能够买下这套房子(第一年房价200万,收入N万)。

输入:

有多行,每行两个整数N(10<=N<=50), K(1<=K<=20)。

输出:

针对每组数据,如果在第21年或者之前就能买下这套房子,则输出一个整数M,表示最早需要在第M年能买下,否则输出Impossible,输出需要换行。

思路:直接模拟,模拟程序员的存款和房价的增长。

def check(x: int, y: int):
    res, price, save = 1, 200, x
    while res <= 21:
        if price <= save:
            return res
        res, price, save = res + 1, price * (1 + y / 100), save + x
    return "Impossible"


while True:
    try:
        n, k = map(int, input().split())
        print(check(n, k))
    except:
        break

问题 F: 大整数乘法

题目描述:

使用分治算法实现两个大整数相乘。

输入:
两个十进制大整数,满足每一个整数长度为2^n且两个大整数的长度相等。(多组数据)

输出:

两个大整数的乘积。

偷鸡:

while True:
    try:
        n1, k1 = map(int, input().split())
        print(n1 * k1)
    except:
        break

思路:待更新...

问题 G: 和费马开个玩笑

题目描述:

费马大定理:当n>2时,不定方程an+bn=cn没有正整数解。比如a3+b3=c3没有正整数解。我们来给他开个玩笑:把方程改成a3+b3=c3,这样就有解了,比如a=4, b=9, c=79时43+93=793。
输入两个整数x, y, 求满足x<=a,b,c<=y的整数解的个数。

输入:

输入最多包含10组数据。每组数据包含两个整数x, y(1<=x,y<=108)。

输出:

对于每组数据,输出解的个数。

思路:双重循环判断,注意结束条件。

cnt = 0
while True:
    try:
        x, y = map(int, input().split())
        res, cnt = 0, cnt + 1
        for a in range(x, min(y + 1, 1001)):
            for b in range(x, a + 1):
                n = a ** 3 + b ** 3
                if n % 10 == 3 and x <= n // 10 <= y:
                    # print(a, b, n)
                    res = res + 2 if a != b else res + 1
        print(f"Case {cnt}: {res}")
    except:
        break

问题 H: 大还是小?

题目描述:

输入两个实数,判断第一个数大,第二个数大还是一样大。每个数的格式为:

[整数部分].[小数部分] 

简单起见,整数部分和小数部分都保证非空,且整数部分不会有前导 0。不过,小数部分的最 后可以有 0,因此 0.0和 0.000是一样大的。 

输入:

输入包含不超过 20组数据。每组数据包含一行,有两个实数(格式如前所述)。每个实数都 包含不超过 100个字符。 

输出:

对于每组数据,如果第一个数大,输出"Bigger"。如果第一个数小,输出"Smaller"。如果两个 数相同,输出"Same"。 

偷鸡:

cnt = 0
while True:
    try:
        x, y = map(float, input().split())
        cnt += 1
        if x < y:
            res = "Smaller"
        elif x == y:
            res = "Same"
        else:
            res = "Bigger"
        print(f"Case {cnt}: {res}")
    except:
        break

思路:因为整数部分没有前导0,所以可以通过判断整数部分的长度初步判断大小。如果长度相等再判断整数的数值大小,还相等的话,再将小数部分对齐补0,判断大小。

def init():
    global df1, df2
    if length3 < length4:
        df1 = df1 + "0" * (length4 - length3)
    else:
        df2 = df2 + "0" * (length3 - length4)


def check(str1: str, str2: str, n: int):
    for i in range(n):
        if str1[i] < str2[i]:
            return -1
        if str1[i] > str2[i]:
            return 1
    return 0


cnt = 0
while True:
    try:
        string1, string2 = input().split()
        i1, df1 = string1.split('.')
        i2, df2 = string2.split('.')
        length1, length2, length3, length4 = len(i1), len(i2), len(df1), len(df2)
        init()
        k, ctl = check(i1, i2, length1), check(df1, df2, max(length3, length4))
        # print(1)
        if length1 < length2 or k == -1 or (k == 0 and ctl == -1):
            res = "Smaller"
        elif length1 > length2 or k == 1 or (k == 0 and ctl == 1):
            res = "Bigger"
        else:
            res = "Same"
        cnt += 1
        print(f"Case {cnt}: {res}")
    except:
        break
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您讲解一下 HNUCM 最小生成树(Prim)的算法过程。 首先,Prim 算法是一种贪心算法,用于求解带权无向连通图的最小生成树。下面是具体的算法过程: 1. 选取任意一个顶点作为起点,将其加入到生成树中。 2. 找到与已经加入到生成树中的顶点相邻的所有顶点,并计算它们与生成树的距离。 3. 从这些顶点中选取距离最小的顶点,将其加入到生成树中。 4. 重复步骤2和3,直到生成树中包含了所有的顶点。 在具体实时,可以使用一个数组来记录每个顶点是否已经加入到生成树中,以及另一个数组来记录每个顶点与生成树的距离。每次选择距离最小的顶点时,可以使用一个最小堆来优化。 至于 HNUCM 最小生成树 Prim 算法的具体实,可以参考以下代码: ```python import heapq def prim(graph): n = len(graph) visited = [False] * n distance = [float('inf')] * n distance[0] = 0 heap = [(0, 0)] result = 0 while heap: (d, u) = heapq.heappop(heap) if visited[u]: continue visited[u] = True result += d for v, weight in graph[u]: if not visited[v] and weight < distance[v]: distance[v] = weight heapq.heappush(heap, (weight, v)) return result ``` 这段代码实HNUCM 最小生成树 Prim 算法的过程,其中 graph 是一个邻接表表示的带权无向连通图,每个元素是一个二元组 (v, w),表示从节点 u 到节点 v 有一条边权为 w 的边。算法的返回值是最小生成树的总权值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值