算法训练营_算法基础

数据结构与算法

算法基础

程序 = 数据结构 + 算法

算法是指对特定问题求解步骤的一种描述

  • 有穷性
  • 确定性
  • 可行性

好算法的标准

  • 正确性:满足具体问题需求,程序运行正常
  • 易读性:简洁易懂,方便调试修改
  • 健壮性:输入错误时,程序能正确处理
  • 高效性:算法运行效率高,运行时间短
  • 低存储性:所需要的存储空间低

高效率,低存储

时间复杂度:一般将算法的执行次数作为时间复杂度的度量标准

sum = 0                         # 运行 1 次
total = 0                       # 运行 1 次
for i in range(1, n + 1):       # 运行 n + 1 次
    sum = sum + i               # 运行 n 次
    for j in range(1, n + 1):   # 运行 n * (n + 1)次
        total = total + i * j   # 运行 n * n 次

把所有的运行次数加起来:
T ( n ) = 2 n 2 + 3 n + 3 T(n) = 2n^2 + 3n + 3 T(n)=2n2+3n+3
当 n 足够大时,算法的运行时间主要取决于第一项, T ( n ) = O ( n 2 ) T(n) = O(n^2) T(n)=O(n2),O 符号表示时间复杂度上界

空间复杂度:一般将算法的辅助空间作为衡量空间复杂度的标准

mySwap(a, b):
    temp = a    # temp 为辅助空间
    a = b
    b = temp

常见时间复杂度关系:
O ( 1 ) < O ( log ⁡ ( n ) ) < O ( n ) < O ( n log ⁡ ( n ) ) < O ( n 2 ) < O ( 2 n ) < O ( n ! ) < O ( n n ) O(1) < O(\log(n)) < O(n) < O(n\log(n)) < O(n^2) < O(2^n) < O(n!) < O(n^n) O(1)<O(log(n))<O(n)<O(nlog(n))<O(n2)<O(2n)<O(n!)<O(nn)

洛谷官网: https://www.luogu.com.cn/

小玉买文具

题目描述

班主任给小玉一个任务,到文具店里买尽量多的签字笔。已知一只签字笔的价格是 1 1 1 9 9 9 角,而班主任给小玉的钱是 a a a b b b 角,小玉想知道,她最多能买多少只签字笔呢。

输入格式

输入只有一行两个整数,分别表示 a a a b b b

输出格式

输出一行一个整数,表示小玉最多能买多少只签字笔。

样例 #1
样例输入 #1
10 3
样例输出 #1
5
提示
数据规模与约定

对于全部的测试点,保证 0 ≤ a ≤ 1 0 4 0 \leq a \leq 10^4 0a104 0 ≤ b ≤ 9 0 \leq b \leq 9 0b9

解题思路

把元化成角即可在同一个计量单位下计算

penCost = 19
nums = input().split()
a = int(nums[0])
b = int(nums[1])
res = (a * 10 + b) // penCost
print(res)

小鱼的游泳时间

题目描述

伦敦奥运会要到了,小鱼在拼命练习游泳准备参加游泳比赛,可怜的小鱼并不知道鱼类是不能参加人类的奥运会的。

这一天,小鱼给自己的游泳时间做了精确的计时(本题中的计时都按 24 24 24 小时制计算),它发现自己从 a a a b b b 分一直游泳到当天的 c c c d d d 分,请你帮小鱼计算一下,它这天一共游了多少时间呢?

小鱼游的好辛苦呀,你可不要算错了哦。

输入格式

一行内输入四个整数,以空格隔开,分别表示题目中的 a , b , c , d a, b, c, d a,b,c,d

输出格式

一行内输出两个整数 e e e f f f,用空格间隔,依次表示小鱼这天一共游了多少小时多少分钟。其中表示分钟的整数 f f f 应该小于 60 60 60

样例 #1
样例输入 #1
12 50 19 10
样例输出 #1
6 20
提示

对于全部测试数据, 0 ≤ a , c ≤ 24 0\le a,c \le 24 0a,c24 0 ≤ b , d ≤ 60 0\le b,d \le 60 0b,d60,且结束时间一定晚于开始时间。

解题思路

先将小时转换成分钟,用分钟计算完后再转换为小时和分钟即可

nums = input().split()
a = int(nums[0])
b = int(nums[1])
c = int(nums[2])
d = int(nums[3])

sumMinus = (c * 60 + d) - (a * 60 + b)
resH = sumMinus // 60
resM = sumMinus % 60

print("%d %d" % (resH, resM))

[COCI2006-2007#2] R2

题面翻译

S = R 1 + R 2 2 S= \dfrac{R_1+R_2}{2} S=2R1+R2,给定 R 1 R_1 R1 S S S ( − 1000 ≤ R 1 , S ≤ 1000 ) (-1000 \le R_1,S \le 1000) (1000R1,S1000),求 R 2 R_2 R2

题目描述

The number S is called the mean of two numbers R1 and R2 if S is equal to (R1+R2)/2. Mirko’s birthday present for Slavko was two integers R1 and R2. Slavko promptly calculated their mean which also happened to be an integer but then lost R2! Help Slavko restore R2.

输入格式

The first and only line of input contains two integers R1 and S, both between -1000 and 1000.

输出格式

Output R2 on a single line.

样例 #1
样例输入 #1
11 15
样例输出 #1
19
样例 #2
样例输入 #2
4 3
样例输出 #2
2
解题思路

2 S − R 1 = R 2 2S - R_1 = R_2 2SR1=R2

nums = input().split()
R1 = int(nums[0])
S = int(nums[1])
R2 = 2 * S - R1
print(R2)

最长连号

题目描述

输入长度为 n n n 的一个正整数序列,要求输出序列中最长连号的长度。

连号指在序列中,从小到大的连续自然数。

输入格式

第一行,一个整数 n n n

第二行, n n n 个整数 a i a_i ai,之间用空格隔开。

输出格式

一个数,最长连号的个数。

样例 #1
样例输入 #1
10
1 5 6 2 3 4 5 6 8 9
样例输出 #1
5
提示
数据规模与约定

对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 1 0 4 1 \leq n \leq 10^4 1n104 1 ≤ a i ≤ 1 0 9 1 \leq a_i \leq 10^9 1ai109

解题思路

设置一个maxRes用来记录最终的最大长度,设置一个currentRes用来记录当前的连号长度,通过一次循环遍历更新连号情况

n = int(input())
nums = input().split()
maxRes = 1
currentRes = 1
nums = [int(i) for i in nums]
for i in range(n):
    if i > 0 and nums[i] == nums[i - 1] + 1:
        currentRes += 1
    else:
        maxRes = max(maxRes, currentRes)
        currentRes = 1
maxRes = max(maxRes, currentRes)
print(maxRes)

[USACO09OCT] The Robot Plow G

题目描述

Farmer John has purchased a new robotic plow in order to relieve him from the drudgery of plowing field after field after field. It achieves this goal but at a slight disadvantage: the robotic plow can only plow in a perfect rectangle with sides of integer length.

Because FJ’s field has trees and other obstacles, FJ sets up the plow to plow many different rectangles, which might end up overlapping. He’s curious as to just how many squares in his field are actually plowed after he programs the plow with various plow instructions, each of which describes a rectangle by giving its lower left and upper right x,y coordinates.

As usual, the field is partitioned into squares whose sides are parallel to the x and y axes. The field is X squares wide and Y squares high (1 <= X <= 240; 1 <= Y <= 240). Each of the I (1 <= I <= 200) plow instructions comprises four integers: Xll, Yll, Xur, and Yur (1 <= Xll <= Xur; Xll <= Xur <= X; 1 <= Yll <= Yur; Yll <= Yur <= Y) which are the lower left and upper right coordinates of the rectangle to be plowed. The plow will plow all the field’s squares in the range (Xll…Xur, Yll…Yur) which might be one more row and column than would initially be assumed (depending on how you go about your assumptions, of course).

Consider a field that is 6 squares wide and 4 squares high. As FJ issues a pair of plowing instructions (shown), the field gets plowed as shown by ‘*’ and ‘#’ (normally plowed field all looks the same, but ‘#’ shows which were most recently plowed):

......             **....             #####. 
......  (1,1)(2,4) **....  (1,3)(5,4) #####. 
......             **....             **.... 
......             **....             **.... 

A total of 14 squares are plowed.

POINTS: 25

Farmer John为了让自己从无穷无尽的犁田工作中解放出来,于是买了个新机器人帮助他犁田。这个机器人可以完成犁田的任务,可惜有一个小小的缺点:这个犁田机器人一次只能犁一个边的长度是整数的长方形的田地。

因为FJ的田地有树和其它障碍物,所以FJ设定机器人去犁很多不同的长方形。这些长方形允许重叠。他给机器人下了P个指令,每个指令包含一个要犁长方形的地。这片田地由长方形的左下角和右上角坐标决定。他很好奇最后到底有多少个方格的地被犁过了。

一般来说,田地被分割为很多小方格。这些方格的边和x轴或y轴平行。田地的宽度为X个方格,高度为Y个方格 (1 <= X <= 240; 1 <= Y <= 240). FJ执行了I (1 <= I <= 200)个指令,每个指令包含4个整数:Xll, Yll, Xur, Yur (1 <= Xll <= Xur; Xll <= Xur <=X; 1 <= Yll <= Yur; Yll <= Yur <= Y), 分别是要犁的长方形的左下角坐标和右上角坐标。机器人会犁所有的横坐标在Xll…Xur并且纵坐标在Yll…Yur范围内的所有方格的地。可能这个长方形会比你想象的多一行一列(就是说从第Xll列到第Xur列一共有Xur - Xll + 1列而不是Xur - Xll列)。

考虑一个6方格宽4方格高的田地。FJ进行了2个操作(如下),田地就被犁成"*“和”#“了。虽然一般被犁过的地看起来都是一样的。但是标成”#"可以更清晰地看出最近一次被犁的长方形。

一共14个方格的地被犁过了。

输入格式

* Line 1: Three space-separated integers: X, Y, and I

* Lines 2…I+1: Line i+1 contains plowing instruction i which is described by four integers: Xll, Yll, Xur, and Yur

输出格式

* Line 1: A single integer that is the total number of squares plowed

样例 #1
样例输入 #1
6 4 2 
1 1 2 4 
1 3 5 4
样例输出 #1
14
提示

As in the task’s example.

解题思路

使用bool数组对已经犁过的地进行记录

X, Y, I = map(int, input().split())
cmd = [list(map(int, input().split())) for _ in range(I)]
field = [[False for _ in range(Y)] for _ in range(X)]

for k in range(I):
    for i in range(cmd[k][0] - 1, cmd[k][2]):
        for j in range(cmd[k][1] - 1, cmd[k][3]):
            field[i][j] = True

cnt = sum(row.count(True) for row in field)

print(cnt)

[COCI2006-2007#1] Modulo

题面翻译

给出 10 10 10 个整数,问这些整数除以 42 42 42 后得到的余数有多少种。

  • 第一个样例的十个结果是 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 1,2,3,4,5,6,7,8,9,10 1,2,3,4,5,6,7,8,9,10,有 10 10 10 个不同的结果;
  • 第二个样例结果都是 0 0 0,只有一个不同的结果;
  • 第三个样例余数是 39 , 40 , 41 , 0 , 1 , 2 , 40 , 41 , 0 , 1 39,40,41,0,1,2,40,41,0,1 39,40,41,0,1,2,40,41,0,1,有 0 , 1 , 2 , 39 , 40 , 41 0,1,2,39,40,41 0,1,2,39,40,41 这六个不同的结果。
题目描述

Given two integers A and B, A modulo B is the remainder when dividing A by B. For example, the numbers 7, 14, 27 and 38 become 1, 2, 0 and 2, modulo 3. Write a program that accepts 10 numbers as input and outputs the number of distinct numbers in the input, if the numbers are considered modulo 42.

输入格式

The input will contain 10 non-negative integers, each smaller than 1000, one per line.

输出格式

Output the number of distinct values when considered modulo 42 on a single line.

样例 #1
样例输入 #1
1
2
3
4
5
6
7
8
9
10
样例输出 #1
10
样例 #2
样例输入 #2
42
84
252
420
840
126
42
84
420
126
样例输出 #2
1
样例 #3
样例输入 #3
39
40
41
42
43
44
82
83
84
85
样例输出 #3
6
提示

In the first example, the numbers modulo 42 are 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10.
In the second example all numbers modulo 42 are 0.
In the third example, the numbers modulo 42 are 39, 40, 41, 0, 1, 2, 40, 41, 0 and 1. There are 6 distinct numbers.

解题思路

设计一个42长度的数组用来存储所有的余数结果,然后遍历数组,如果某个余数出现过,则将其置为True,最后统计True的个数即为答案。

mod42 = [False] * 42
for i in range(10):
    mod42[int(input()) % 42] = True

sumMod42 = sum(1 for x in mod42 if x)

print(sumMod42)

子数整数

题目描述

对于一个五位数 a 1 a 2 a 3 a 4 a 5 ‾ \overline{a_1a_2a_3a_4a_5} a1a2a3a4a5,可将其拆分为三个子数:

s u b 1 = a 1 a 2 a 3 ‾ sub_1=\overline{a_1a_2a_3} sub1=a1a2a3

s u b 2 = a 2 a 3 a 4 ‾ sub_2=\overline{a_2a_3a_4} sub2=a2a3a4

s u b 3 = a 3 a 4 a 5 ‾ sub_3=\overline{a_3a_4a_5} sub3=a3a4a5

例如,五位数 20207 20207 20207 可以拆分成

s u b 1 = 202 sub_1=202 sub1=202

s u b 2 = 020   ( = 20 ) sub_2=020\ (=20) sub2=020 (=20)

s u b 3 = 207 sub_3=207 sub3=207

现在给定一个正整数 K K K,要求你编程求出 10000 10000 10000 30000 30000 30000 之间所有满足下述条件的五位数,条件是这些五位数的三个子数 s u b 1 , s u b 2 , s u b 3 sub_1,sub_2,sub_3 sub1,sub2,sub3 都可被 K K K 整除。

输入格式

一个正整数 K K K

输出格式

每一行为一个满足条件的五位数,要求从小到大输出。不得重复输出或遗漏。如果无解,则输出 No

样例 #1
样例输入 #1
15
样例输出 #1
22555
25555
28555
30000
提示

0 < K < 1000 0<K<1000 0<K<1000

解题思路

使用整除和模运算对整数进行截断

K = int(input())
flag = False

for i in range(10000, 30001):
    sub1 = i // 100
    sub2 = i // 10 % 1000
    sub3 = i % 1000
    if sub1 % K == 0 and sub2 % K == 0 and sub3 % K == 0:
        print(i)
        flag = True


if flag == False:
    print("No")

三角函数

题目描述

输入一组勾股数 a , b , c ( a ≠ b ≠ c ) a,b,c(a\neq b\neq c) a,b,ca=b=c,用分数格式输出其较小锐角的正弦值。(要求约分。)

输入格式

一行,包含三个正整数,即勾股数 a , b , c a,b,c a,b,c(无大小顺序)。

输出格式

一行,包含一个分数,即较小锐角的正弦值

样例 #1
样例输入 #1
3 5 4
样例输出 #1
3/5
提示

数据保证: a , b , c a,b,c a,b,c 为正整数且 ∈ [ 1 , 1 0 9 ] \in [1,10^9] [1,109]

解题思路

较小锐角的正弦值就是最短边对应的正弦值,因为是直角三角形,只要最短边比最长边就行了

之后需要约分,需要找到最大公约数进行约分(gcd方法),在python中直接使用fractions模块中的Fraction类即可

from fractions import Fraction

a, b, c = map(int, input().split())

up = min(a, b, c)
down = max(a, b, c)

print(Fraction(up, down))

[USACO08OCT] Bovine Bones G

题面翻译

贝茜喜欢玩棋盘游戏和角色扮演游戏,所以她说服了约翰开车带她去小商店.在那里她买了三个骰子。这三个不同的骰子的面数分别为 s 1 , s 2 , s 3 s_1,s_2,s_3 s1,s2,s3

对于一个有 S S S 个面的骰子每个面上的数字是 1 , 2 , 3 , … , S 1,2,3,\ldots,S 1,2,3,,S。每个面(上的数字)出现的概率均等。贝茜希望找出在所有“三个面上的数字的和”中,哪个和的值出现的概率最大。

现在给出每个骰子的面数,需要求出哪个所有“三个面上的数字的和”出现得最频繁。如果有很多个和出现的概率相同,那么只需要输出最小的那个。

数据范围: 2 ≤ s 1 ≤ 20 2\le s_1\leq 20 2s120 2 ≤ s 2 ≤ 20 2 \leq s_2\leq 20 2s220 2 ≤ s 3 ≤ 40 2 \leq s_3\leq 40 2s340

题目描述

Bessie loves board games and role-playing games so she persuaded Farmer John to drive her to the hobby shop where she purchased three dice for rolling. These fair dice have S1, S2, and S3 sides

respectively (2 <= S1 <= 20; 2 <= S2 <= 20; 2 <= S3 <= 40).

Bessie rolls and rolls and rolls trying to figure out which three-dice sum appears most often.

Given the number of sides on each of the three dice, determine which three-dice sum appears most frequently. If more than one sum can appear most frequently, report the smallest such sum.

POINTS: 70

输入格式

* Line 1: Three space-separated integers: S1, S2, and S3

输出格式

* Line 1: The smallest integer sum that appears most frequently when the dice are rolled in every possible combination.

样例 #1
样例输入 #1
3 2 3
样例输出 #1
5
提示

Here are all the possible outcomes.

1 1 1 -> 3  
1 2 1 -> 4  
2 1 1 -> 4  
2 2 1 -> 5  
3 1 1 -> 5  
3 2 1 -> 6 
1 1 2 -> 4  
1 2 2 -> 5  
2 1 2 -> 5  
2 2 2 -> 6  
3 1 2 -> 6  
3 2 2 -> 7 
1 1 3 -> 5  
1 2 3 -> 6  
2 1 3 -> 6  
2 2 3 -> 7  
3 1 3 -> 7  
3 2 3 -> 8

Both 5 and 6 appear most frequently (five times each), so 5 is the answer.

解题思路

使用数组记录所有和出现的次数,然后遍历数组,找出最小,出现次数最多的和

S1, S2, S3 = map(int, input().split())
sumList = [0] * 81

for i in range(1, S1 + 1):
    for j in range(1, S2 + 1):
        for k in range(1, S3 + 1):
            sumList[i + j + k] += 1

maxSum = 0
maxI = 0
for i in range(1, 81):
    if maxSum < sumList[i]:
        maxSum = sumList[i]
        maxI = i

print(maxI)

不高兴的津津(升级版)

题目描述

津津上初中了。妈妈认为津津应该更加用功学习,所以津津除了上学之外,还要参加妈妈为她报名的各科复习班。另外每天妈妈还会送她去学习朗诵、舞蹈和钢琴。但是津津如果一天上课超过八个小时就会不高兴,而且上得越久就会越不高兴。

这次与 NOIp2004 普及组第一题不同的是:假设津津不会因为其它事不高兴,但是她的不高兴会(当然高兴也会)持续到第二天。请你帮忙检查一下津津以后 n n n 天的日程安排,看看以后 n n n 天她会不会不高兴(计算方法:用昨天不高兴程度加上今天上课总时间减去 8 8 8 后得到的数作为今天不高兴程度);输出以后 n n n 天结束后不高兴程度和是多少。

输入格式

第一行共一个数 n n n

第二行至第 n + 1 n+1 n+1 行,每行两个数,表示这天上学时间和课外补习班时间。

输出格式

一个数,这 n n n 天过后的不高兴程度和。

样例 #1
样例输入 #1
7
5 3
6 2
7 2
5 3
5 4
0 4
0 6
样例输出 #1
-2
提示
数据范围及约定

对于全部数据,上学时间和上课时间各不超过 8 8 8,和不超过 16 16 16 n ≤ 3000 n \le 3000 n3000

解题思路

根据题目的计算方法计算每一天的不开心值,然后求和

n = int(input())
unhappy = 0
unhappySum = 0
for i in range(n):
    a, b = map(int, input().split())
    unhappy = unhappy + a + b - 8
    unhappySum = unhappySum + unhappy

print(unhappySum)

[COCI2006-2007#1] Herman

题面翻译

19世纪的德国数学家赫尔曼·闵可夫斯基(Hermann Minkowski)研究了一种名为出租车几何学的非欧几何。
在出租车几何里 T 1 ( x 1 , y 1 ) T_1(x_1,y_1) T1(x1,y1) T 2 ( x 2 , y 2 ) T_2(x_2,y_2) T2(x2,y2)两点之间的距离被定义为 d i s ( T 1 , T 2 ) = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ dis(T_1,T_2)=|x_1-x_2|+|y_1-y_2| dis(T1,T2)=x1x2+y1y2(曼哈顿距离)。
其他定义均与欧几里得几何相同。
例如圆的定义:在同一平面内,到定点(圆心)的距离等于定长(半径)的点的集合。

我们对欧几里得几何与出租车几何两种定义下半径为 R R R的圆的面积很感兴趣。解决这个问题的重担就落在你身上了。

输入输出格式
输入格式

仅有一行为圆的半径 R R R ( R ≤ 10000 ) (R \leq 10000) (R10000)

输出格式

第一行输出欧几里得几何下半径为 R R R的圆的面积,第二行输出出租车几何下半径为 R R R的圆的面积。

注意:你的输出与标准答案绝对误差不超过 0.0001 0.0001 0.0001将会被认为正确

题目描述

The 19th century German mathematician Hermann Minkowski investigated a non-Euclidian geometry, called the taxicab geometry. In taxicab geometry the distance between two points T1(x1, y1) and T2(x2, y2) is defined as:
D(T1,T2) = |x1 - x2| + |y1 - y2|
All other definitions are the same as in Euclidian geometry, including that of a circle:
A circle is the set of all points in a plane at a fixed distance (the radius) from a fixed point (the centre of the circle).
We are interested in the difference of the areas of two circles with radius R, one of which is in normal (Euclidian) geometry, and the other in taxicab geometry. The burden of solving this difficult problem has fallen onto you.

输入格式

The first and only line of input will contain the radius R, an integer smaller than or equal to 10000.

输出格式

On the first line you should output the area of a circle with radius R in normal (Euclidian) geometry.
On the second line you should output the area of a circle with radius R in taxicab geometry.
Note: Outputs within ±0.0001 of the official solution will be accepted.

样例 #1
样例输入 #1
1
样例输出 #1
3.141593
2.000000
样例 #2
样例输入 #2
21
样例输出 #2
1385.442360
882.000000
样例 #3
样例输入 #3
42
样例输出 #3
5541.769441
3528.000000
解题思路

设一个点 ( x , y ) (x,y) (x,y)到原点 ( 0 , 0 ) (0,0) (0,0)的距离为 R R R
根据欧几里得距离公式两点间的距离 D = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 D = \sqrt{(x_1-x_2)^2+(y_1-y_2)^2} D=(x1x2)2+(y1y2)2
R = x 2 + y 2 R = \sqrt{x^2+y^2} R=x2+y2 ,圆的方程为 x 2 + y 2 = R 2 x^2+y^2=R^2 x2+y2=R2
欧几里得圆
面积计算公式为 S = π R 2 S = \pi R^2 S=πR2

根据出租车几何距离公式两点间的距离 D = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ D = |x_1-x_2|+|y_1-y_2| D=x1x2+y1y2
R = ∣ x ∣ + ∣ y ∣ R = |x|+|y| R=x+y
出租车圆
面积计算公式为 S = 2 R 2 S = 2 R^2 S=2R2

import math

R = int(input())
res1 = math.pi * R * R
res2 = 2 * R * R
print("%.6f" % res1)
print("%.6f" % res2)

月落乌啼算钱(斐波那契数列)

题目背景

(本道题目木有隐藏歌曲……不用猜了……)

《爱与愁的故事第一弹·heartache》最终章。

吃完 pizza,月落乌啼知道超出自己的预算了。为了不在爱与愁大神面前献丑,只好还是硬着头皮去算钱……

题目描述

算完钱后,月落乌啼想着:“你坑我!”于是当爱与愁大神问多少钱时,月落乌啼说了一堆乱码。爱与愁大神说:“算了算了,我只问第 n n n 样菜价格多少?”月落乌啼写出了:

F n = ( 1 + 5 2 ) n − ( 1 − 5 2 ) n 5 F_n=\dfrac{\left(\frac{1+\sqrt{5}}{2}\right)^n-\left(\frac{1-\sqrt{5}}{2}\right)^n}{\sqrt{5}} Fn=5 (21+5 )n(215 )n

由于爱与愁大神学过编程,于是就用 1 1 1 分钟的时间求出了 F n F_n Fn 的结果。月落乌啼为此大吃一惊。你能学学爱与愁大神求出 F n F_n Fn 的值吗?

输入格式

一行一个自然数 n n n

输出格式

只有 1 1 1 行一个实数 F n F_n Fn,保留两位小数。

样例 #1
样例输入 #1
6
样例输出 #1
8.00
提示

对于所有数据: 0 ≤ n ≤ 48 0 \leq n\leq 48 0n48

解题思路

直接写公式

import math

n = int(input())

res = (((1 + math.sqrt(5)) / 2) ** n - ((1 - math.sqrt(5)) / 2) ** n) / math.sqrt(5)
print("%.2f" % res)

这个公式是斐波那契数列的通项公式,可以利用递推公式求解

n = int(input())

a0 = 0
a1 = 1

# Fn = Fn-1 + Fn-2
for i in range(2, n + 2):
    (a0, a1) = (a1, a0 + a1)

print("%.2f" % a0)

pb的游戏(1)

题目背景

有一天 pb 和 zs 玩游戏 你需要帮 zs 求出每局的胜败情况。

题目描述

游戏规则是这样的:

  • 先手对给出的数进行分割,分割成两个正整数,之后接着后手选择留下两个数中的其中一个。两人轮流操作,直到一方无法操作,另一方胜利。

现在要你求出 N N N 次游戏的胜败。

我们认为双方绝顶聪明。每局由 pb 先进行分割。如果 pb 存在必胜策略,输出 pb wins;否则输出 zs wins

输入格式

第一行一个数 N N N,表示数据组数。

之后 N N N 行,每行一个数 M M M,表示每局初始的数。

输出格式

N N N 行,每行一串字符,表示游戏结果。

样例 #1
样例输入 #1
5
1
3
7
20
5
样例输出 #1
zs wins
zs wins
zs wins
pb wins
zs wins
提示

对于全部数据, 1 < N < 50 1<N<50 1<N<50 1 ≤ M ≤ 1 0 9 1\le M\le 10^9 1M109

解题思路

选择偶数的一方必胜
偶数必可以拆分
偶数可以拆成1+奇数,另一方就不得不选择奇数,而奇数又必拆成奇数+偶数,因此又可以选择偶数
最后偶数拆分成1+1,另一方必败

程序最后化简成判断一个数是奇数还是偶数

def myTest(t):
    if t % 2 == 0:
        print("pb wins")
    else:
        print("zs wins")


n = int(input())
for i in range(n):
    t = int(input())
    myTest(t)

小鱼的数字游戏

题目描述

小鱼最近被要求参加一个数字游戏,要求它把看到的一串数字 a i a_i ai(长度不一定,以 0 0 0 结束),记住了然后反着念出来(表示结束的数字 0 0 0 就不要念出来了)。这对小鱼的那点记忆力来说实在是太难了,你也不想想小鱼的整个脑袋才多大,其中一部分还是好吃的肉!所以请你帮小鱼编程解决这个问题。

输入格式

一行内输入一串整数,以 0 0 0 结束,以空格间隔。

输出格式

一行内倒着输出这一串整数,以空格间隔。

样例 #1
样例输入 #1
3 65 23 5 34 1 30 0
样例输出 #1
30 1 34 5 23 65 3
提示
数据规模与约定

对于 100 % 100\% 100% 的数据,保证 0 ≤ a i ≤ 2 31 − 1 0 \leq a_i \leq 2^{31} - 1 0ai2311,数字个数不超过 100 100 100

解题思路

直接使用反转函数即可,也可以使用栈进行反转

nums = list(map(int, input().split()))
nums.reverse()
for i in range(1, len(nums)):
    if i != 1:
        print(" ", end="")
    print("%d" % nums[i], end="")
print()

HXY玩卡片

题目描述

HXY得到了一些卡片,这些卡片上标有数字 0 0 0 5 5 5 。现在她可以选择其中一些卡片排成一列,使得排出的一列数字组成的数最大,且满足被 90 90 90 整除这个条件。同时,这个数必须为合法的某个非负整数,即不能含有前导 0 0 0 ,即 0 0 0 不能作为这串数的首位。但是特殊地,整数 0 0 0 满足条件。如果不能排出这样的数,输出“ − 1 -1 1”。

输入格式

第一行,卡片的个数 n n n

第二行,分别给出了这 n n n 个数(只能为数字 5 5 5 0 0 0 )。

输出格式

仅一行,如果可以排出,则输出这个数。否则输出-1

样例 #1
样例输入 #1
4
5 0 5 0
样例输出 #1
0
样例 #2
样例输入 #2
11
5 5 5 5 5 5 5 5 0 5 5
样例输出 #2
5555555550
样例 #3
样例输入 #3
2
5 5
样例输出 #3
-1
提示

数据范围:

对于 30 % 30\% 30% 的数据, n ≤ 10 n\le 10 n10

对于 20 % 20\% 20% 的数据,仅含数字 5 5 5

对于 100 % 100\% 100% 的数据, n ≤ 1000 n\le 1000 n1000

解题思路

一个数要能被90整除,即它既要能被10整除,又要能被9整除,因此最后一位必须是0(被10整除),且去除最后一位0后,前面的数字需要被9整除。前面的数字只能由5和0组成,要被9整除就需要5有9的倍数个。题目要求最大的结果,因此尽可能地让5靠前

令 cnt0 为 0 的个数,cnt5 为 5 的个数

cnt0 == 0 时,必须输出-1。因为这样的数一定不能被10整出,进而不能被90整除

cnt0 != 0 and cnt5 < 9 时,必须输出0。因为5不足9个,无法凑成9的倍数

cnt0 != 0 and cnt5 >= 9 时,输出9的倍数个5,而后输出cnt0个0,因为不一定要选择所有的5,只要让5凑成9的倍数就足够了,剩下的0拓展位数,尽可能使值增大

n = int(input())
nums = list(map(int, input().split()))
cnt5 = sum(1 for x in nums if x == 5)
cnt0 = n - cnt5

if cnt0 == 0:
    print(-1)
elif cnt5 < 9:
    print(0)
elif cnt5 >= 9:
    k = cnt5 // 9
    print("555555555" * k + "0" * cnt0)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值