1.9更新
- 二分法代碼寫了一下,也是有坑的 ;P
- 貼幾個選擇題相關的鏈接,和老師發的期末范圍
期末考試題型與分值分布:
python語言,4個選擇,2個編程 python基礎語法
算法,2個選擇,2個編程
網絡,5個選擇 http相關
數據思維,5個選擇,2個編程(編程都是numpy) numpy基礎用法
人工智能慕課,4個選擇 人工智能相關
本篇題解每一份代碼都有坑,請慎重復制
1. 上台階
小明要上一個n級台階,他每次可以上1級或者直接上2級,請問小明一共有幾種不同的方法上台階?
例如,對於一個3級的台階,小明有3種不同的方法上去:1)每次上1級。2)先上1級,再直接上2級。3)先直接上2級,再上1級。
- 題解
思考對於第i階台階,可從第i-1階和第i-2階走過來,走到第0/1階都只有1種方式,可寫出遞歸方程
遞歸程序:時間復雜度\(O(2^n)\)
def f(n):
if n==1:
return 1
return f(n-1)+f(n-2)
n=int(input())
print(f(n))
觀察到\(f(i-2)\)還可被\(f((i-1)-1)\)重復調用,可轉化為記憶化搜索(python寫不了,下面是c++),將\(f(i)\)的值在第一次訪問后記錄下來,節省時間/空間。時間復雜度\(O(n)\)(常數較大)
#include<cstdio>
#include<cstring>
int f[10000]
int func(n)
{
return f[n]? f[n]:fn[n]=func(n-1)+func(n-2);
}
int main()
{
int n;
scanf("%d",&n);
printf("%d",func(n));
return 0;
}
記錄后觀察數組數據/轉移方程,可以看出是fib,利用單層循環可解決。時間復雜度\(O(n)\)
f=[0]*1000
n=int(input())
f[0]=1
f[1]=1
for i in range(2,n):
f[i]=f[i-1]+f[i-2]
print(f[n])
此處還可利用線性代數優化時間復雜度到\(O(logn)\)
2. 黃金分割
黃金分割是指將整體一分為二,較大部分與整體部分的比值等於較小部分與較大部分的比值,其比值約為0.618。這個比例被公認為是最能引起美感的比例,因此被稱為黃金分割。
要求:從鍵盤輸入一個整數n作為整體,將n分解為兩個整數n1和n2(假設n1<=n2),使得n1+n2=n,模擬黃金分割,找到n1與n2比值和n2與n比值最接近的那組數據,並且將該比值以及n1、n2的值存入列表並輸出。
例如,n=5,可以分解為[1,4]和[2,3]兩組,滿足上述要求的是[2, 3],將[0.6666666666666666, 2, 3]存入列表並輸出。
- 題解
暴力枚舉每一組拆分情況,找到最接近的解,時間復雜度\(O(n)\)
n = int(input(''))
cek=0.618
E=1e-6
_min=10000000
ans=[]
for i in range(1,n):
if (abs((n-i)/i-cek)<_min):
ans=[(n-i)/i,i,n-i]
_min=abs((n-i)/i-cek)
print(ans)
3. 賣鴨子
一個人趕着鴨子去每個村庄賣,每經過一個村子賣去所趕鴨子的一半又一只。這樣他經過了n個村子后還剩m只鴨子,問他出發時共趕多少只鴨子?(n和m是輸入的已知值)
- 題解
反向看問題,每走過一個村庄得到一只鴨子再翻倍,時間復雜度\(O(n)\)
n = eval(input())
m = eval(input())
while(n!=0):
m=(m+1)*2
print(m)
也可根據二進制特性\(O(1)\)解決
4. 二分法求方程的根
請使用二分法求方程
在范圍內[2,5]之間的根root, 要求f(root)的值與0值的誤差小於等於1e-8。已知f(2)<0, f(5)>0。要求所求根保留8位小數輸出
- 題解
由於已知\(f(2)<0, f(5)>0\)二分答案判斷中點值處函數值大小,根據正負選擇下一步二分區間
import math
def f(x):
return -math.sin(x)*math.e**x+15*math.cos(x)*x**0.5
E=1e-8
l=2
r=5
mid=(l+r)/2
while(abs(f(mid))>E):
if( f(mid)>0):
l=mid
else:
r=mid
mid=(l+r)/2
print(mid)
5.足球比賽
有三只球隊,每只球隊編號分別為球隊1,球隊2,球隊3,這三只球隊一共需要進行 n 場比賽。現在已經踢完了k場比賽,每場比賽不能打平,踢贏一場比賽得一分,輸了不得分不減分。已知球隊1和球隊2的比分相差d1分,球隊2和球隊3的比分相差d2分,每場比賽可以任意選擇兩只隊伍進行。求如果打完最后的 (n-k) 場比賽,有沒有可能三只球隊的分數打平。
輸入描述:
第一行包含一個數字 t (1 <= t <= 10)
接下來的t行每行包括四個數字 n, k, d1, d2(1 <= n <= 10^12; 0 <= k <= n, 0 <= d1, d2 <= k)
輸出描述:
每行的比分數據,最終三只球隊若能夠打平,則輸出“yes”,否則輸出“no”
- 題解
簡單的結論題,但因為是結論題所以不簡單........
在踢完\(k\)場比賽后,分數可能有以下四種情況
球隊1 | 球隊2 | 球隊3 | |
---|---|---|---|
1 | x-d1 | x | x-d2 |
2 | x+d1 | x | x-d2 |
3 | x-d1 | x | x+d2 |
4 | x+d1 | x | x+d2 |
根據題意,表格中的任意一個數都應該是正整數,且和為\(k\).則可在上述四種中找出正確的組合.
- 若第一種情況成立,打平需要讓1隊/3隊分別獲得d1/d2分,再將剩下的分數三等分
- 若第二種情況成立,打平需要讓2隊/3隊分別獲得d1/d1+d2分,再將剩下的分數三等分
- 若第三種情況成立,打平需要讓1隊/2隊分別獲得d1+d2/d2分,再將剩下的分數三等分
- 若第四種情況成立,打平需要讓[1/3中較小的一隊]/2隊分別獲得\(max\{d1,d2\}-min\{d1,d2\}\)/\(max\{d1,d2\}\)分,再將剩下的分數三等分
若符合以上四種情況中的任意一種則可輸出'yes',否則輸出'no'
t = int(input())
for i in range(t):
[n, k, d1, d2] = [int(x) for x in input().split(' ')]
r = n - k
if d1>d2:
x = 2*d1-d2
y = d1
else:
x = 2*d2-d1
y = d2
if (r-(2*d1+d2))>=0 and (r-(2*d1+d2))%3==0 and (n-3*(d1+d2))>=0 and (n-3*(d1+d2))%3==0:
print('yes')
elif (r-x)>=0 and (r-x)%3==0 and (n-3*y)>=0 and (n-3*y)%3==0:
print('yes')
elif (r-(d1+d2))>=0 and (r-(d1+d2))%3==0 and (n-3*y)>=0 and (n-3*y)%3==0:
print('yes')
elif (r-(d1+2*d2))>=0 and (r-(d1+2*d2))%3==0 and (n-3*(d1+d2))>=0 or (n-3*(d1+d2))%3==0:
print('yes')
else:
print('no')
6.數組基本操作
創建初始值為1,終值為12,元素個數為12的等差數組,使其元素為整數,改變數組形狀為3行4列的二維數組,將數組中值小於3或大於9的元素值設為0,最后選取數組的第一列和最后一列輸出。
- 題解
考察numpy基本操作 numpy標准文檔
import numpy as np
l=np.arange(1,13,1,int) #創建初始值為1,終值為12,元素個數為12的等差數組,使其元素為整數
x=l.reshape(3,4) #改變數組形狀為3行4列的二維數組
x[x<3]=0
x[x>9]=0 #將數組中值小於3或大於9的元素值設為0
print(x[:,1],x[:,-1]) #最后選取數組的第一列和最后一列輸出
7.九九乘法表
for i in range(1,10):
for j in range(1,i+1):
print('{0}*{1}={2}'.format(i,j,i*j),end=' ')
print()
(不知道為什么過不了,明明和圖片一樣)
8.二分法進行數字查找
請使用二分法在一個升序列表中查找兩個數,使得兩者的立方和等於給定的數X。
如果找到了,請輸出這兩個數,並用空格分隔;如果沒有找到,請輸出-1
- 題解
循環找第一個數,二分找第二個
def find(A,left):
l=0,r=A.len()
while( l < r):
mid=(l+r)//2
if(left == A[mid]**3):return mid
if (left<A[mid**3]):
r=mid
else:
l=mid
return -1
for i in A:
ans=find(A,x-i**3)
if(ans != -1):
print(i,A[ans])
break
if(ans==-1):
print('-1')
9.公式計算並打印
編寫一個程序,根據給定的公式計算並打印值:
以下是C和H的固定值:C是50。H是30。
D是一個變量,它的值應該以逗號分隔的序列輸入到程序中。
import math
c = 50
h=30
t=[]
t = map(int,input().split(','))
for d in t:
print(math.sqrt(2*c*d/h))
這題不知道輸出格式...似乎也過不了
10.數組基本操作
a是一個n行m列的二維數組,求出數組周邊元素之和。
print(l.sum(axis=1)[0]+l.sum(axis=1)[n-1]+l.sum(axis=0)[0]+l.sum(axis=0)[m-1]-l[0][0]-l[0][m-1]-l[n-1][0]-l[n-1][m-1])
11數組基本操作
代碼中score表示n個學生3門功課的成績表,數據已經生成
要求:
1. 求出每門課程的最高分以及對應的行索引,輸出最高分及行索引(從第1行開始計數)。
2. 求出每個學生的平均成績並輸出。
print(np.amax(score,axis=1))
print(np.argmax(score,axis=1))
print(np.mean(score,axis=1))