【我的青春coding物语果然有问题!】MOOC难题复盘

好快啊

这个系列马上就要结束了,然后就要迎接下学期的数算A
注:上期提出的整活标题不一定实际应用于下学期的博客标题
我们直接看题吧

0528:派

描述

我的生日要到了!根据习俗,我需要将一些派分给大家。我有N个不同口味、不同大小的派。有F个朋友会来参加我的派对,每个人会拿到一块派(必须一个派的一块,不能由几个派的小块拼成;可以是一整个派)。

我的朋友们都特别小气,如果有人拿到更大的一块,就会开始抱怨。因此所有人拿到的派是同样大小的(但不需要是同样形状的),虽然这样有些派会被浪费,但总比搞砸整个派对好。当然,我也要给自己留一块,而这一块也要和其他人的同样大小。

请问我们每个人拿到的派最大是多少?每个派都是一个高为1,半径不等的圆柱体。

输入

第一行包含两个正整数N和F,1 ≤ N, F ≤ 10 000,表示派的数量和朋友的数量。
第二行包含N个1到10000之间的整数,表示每个派的半径。

输出

输出每个人能得到的最大的派的体积,精确到小数点后三位。

样例输入

3 3
4 3 3

样例输出

25.133

Solution

这道题一看就是要二分了 因为这个条件包括这个精确到小数点后第三位,就是在找一个满足条件的最小值
就是,浮点数的二分容易忘记怎么写,我们这里可以再看一下

pi=3.1415926536
lst=input().split()
n=int(lst[0])
f=int(lst[1])
k=input().split()
ans=[0]
mr=0
for i in range(1,n+1):  
    ans.append(pi*int(k[i-1])*int(k[i-1]))
    mr=max(mr,int(k[i-1]))
l=0
r=pi*mr*mr+1
eps=1e-6
res=0
while r-l>=eps:
    mid=(l+r)/2
    temp=0
    for i in range(1,n+1):
        temp+=ans[i]//mid
    if temp>=f+1:
        l=mid+eps
        res=mid
    else:
        r=mid-eps
print(f"{res:.3f}")

0610:图像模糊处理

描述

给定n行m列的图像各像素点的灰度值,要求用如下方法对其进行模糊化处理:

  1. 四周最外侧的像素点灰度值不变;

  2. 中间各像素点新灰度值为该像素点及其上下左右相邻四个像素点原灰度值的平均(舍入到最接近的整数)。

输入

第一行包含两个整数n和m,表示图像包含像素点的行数和列数。1 <= n <= 100,1 <= m <= 100。
接下来n行,每行m个整数,表示图像的每个像素点灰度。相邻两个整数之间用单个空格隔开,每个元素均在0~255之间。

输出

n行,每行m个整数,为模糊处理后的图像。相邻两个整数之间用单个空格隔开。

样例输入

4 5
100 0 100 0 50
50 100 200 0 0
50 50 100 100 200
100 100 50 50 100

样例输出

100 0 100 0 50
50 80 100 60 0
50 80 100 90 200
100 100 50 50 100

Solution

这道题当然就是开两个数组,一个记录原来的数据,另一个记录后面的数据
但是,我想不明白的一点是,不知道为什么,当直接把temp这个列表输入地图列表的时候,会出现两个被同时修改的情况,一个一个输进去反而没啥事
所以,还是一个一个输进去吧

lst=input().split()
n=int(lst[0])
m=int(lst[1])
ma=[[0]]
fa=[[0]]
dx=[0,1,-1,0,0]
dy=[0,0,0,1,-1]
for i in range(1,n+1):
    lst=input().split()
    ma.append([0])
    fa.append([0])
    for j in range(1,m+1):
        ma[i].append(int(lst[j-1]))
        fa[i].append(int(lst[j-1]))
for i in range(2,n):
    for j in range(2,m):
        temp=0
        for k in range(0,5):
            ax=i+dx[k]
            ay=j+dy[k]
            temp+=fa[ax][ay]
        ma[i][j]=round(temp/5)
for i in range(1,n+1):
    for j in range(1,m+1):
        print(ma[i][j],end=' ')
    print()

0150:摄氏华氏温度转换

描述

输入摄氏温度,就将其转换为华氏温度输出;输入华氏温度,就将其转换成摄氏温度数输出。两者的转换关系是:

摄氏温度 = (华氏温度 - 32 ) ÷ 1.8

输入

摄氏温度或华氏温度。摄氏温度的格式是一个整数或小数后面加'C'或'c',华氏温度的格式是一个整数或小数后面加'F'或'f'。

输出

转换后的温度。摄氏温度就在数值后面加'C',华氏温度就在数值后面加'F'。如果数值是整数,就应该输出整数形式,如果数值是小数,则保留小数点后面2位。

样例输入

样例1
33.8F
样例2
43C 
样例3
12.8c

样例输出

样例1
1C
样例2
109.40F
样例3
55.04F

Solution

这道题最关键的是我们要怎么判断一个数是整数(你没有听错)
就是,我们用浮点数处理出来的,我们以为是1的数,竟然是0.9999999984?
这时候,就得用round出马了

lst=input()
num=0
if lst[len(lst)-1]=='F' or lst[len(lst)-1]=='f':
    num=float(lst[:len(lst)-1])
    res=(num-32)*1.0/1.8
    if abs(round(res)-res)<=1e-4:
        print(round(res),end='')
        print('C')
    else:
        print(f"{res:.2f}",end='')
        print('C')
else:
    num=float(lst[:len(lst)-1])
    res=num*1.8+32
    tem=int(res)
    if res==tem:
        print(tem,end='')
        print('F')
    else:
        print(f"{res:.2f}",end='')
        print('F')

0700:找出全部子串位置

描述

输入两个串s1,s2,找出s2在s1中所有出现的位置

两个子串的出现不能重叠。例如'aa'在 aaaa 里出现的位置只有0,2

输入

第一行是整数n
接下来有n行,每行两个不带空格的字符串s1,s2

输出

对每行,从小到大输出s2在s1中所有的出现位置。位置从0开始算
如果s2没出现过,输出 "no"
行末多输出空格没关系

样例输入

4
ababcdefgabdefab ab
aaaaaaaaa a
aaaaaaaaa aaa 
112123323 a

样例输出

0 2 9 14 
0 1 2 3 4 5 6 7 8 
0 3 6 
no

Solution

我们需要对原来的字符串进行不断切片,然后用while循环逐个找出子串的位置
小技巧:不需要逐个切片,我们直接记录每次切到哪里就可以了,这样反而不容易妨碍编码

n=int(input())
for i in range(1,n+1):
    lst=input().split()
    s1=lst[0]
    s2=lst[1]
    l=0
    ans=0
    while True:
        if s1.find(s2,l)==-1:
            break
        ans+=1
        print(s1.find(s2,l),end=' ')
        l=s1.find(s2,l)+len(s2)
    if ans==0:
        print("no")
    else:
        print()

0730:万年历

描述

给定年月日,求星期几。已知2020年11月18日是星期三。另外,本题有公元0年,这个和真实的纪年不一样

输入

第一行是n(n <=30),表示有n组数据
接下来n行,每行是一组数据。
每行三个整数y,m,d,分别代表年,月,日。(-1000000<=y<=1000000)

若今年是2017年,则往前就是2016年,2015年....一直数到2年,1年,再往前就是0年,-1年,-2年.....

输出

对每组数据,输出星期几,星期几分别用

"Sunday","Monday","Tuesday","Wednesday","Thursday", "Friday","Saturday" 表示

如果月份和日期不合法,输出"Illegal"

样例输入

6
2017 2 29
2017 13 2
0 1 1
-2 3 4
2017 10 18
2015 12 31

样例输出

Illegal
Illegal
Saturday
Wednesday
Wednesday
Thursday

Solution

这道题就是纯粹的大模拟
当然了,我们需要首先考虑的是,公元0年1月1日是星期几?
这个是非常关键的,因为它在不同计时法下,会有变化
好了,剩下就是对年份的处理了,尤其需要注意的是闰年到底有多少年这种,可以举特例来debug

def pd(x):
    if x%4==0 and x%100!=0:
        return True
    if x%400==0:
        return True
    return False
n=int(input())
rc=[0,31,29,31,30,31,30,31,31,30,31,30,31,30]
c=[0,31,28,31,30,31,30,31,31,30,31,30,31,30]
dd=["","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]
for i in range(1,n+1):
    lst=input().split()
    y=int(lst[0])
    m=int(lst[1])
    d=int(lst[2])
    day=0
    if m>=13:
        print("Illegal")
        continue
    if pd(y):
        if d>rc[m] or d<=0:
            print("Illegal")
            continue
    else:
        if d>c[m] or d<=0:
            print("Illegal")
            continue
    if y>=0:
        if pd(y):
            for j in range(1,m):
                day+=rc[j]
        else:
            for j in range(1,m):
                day+=c[j]
        day+=d
        tem=0
        tem=(y-1)//4+(y-1)//400-(y-1)//100
        tem+=1
        if y==0:
            tem=0
        day+=tem*366+(y-tem)*365
        res=(day+5)%7
        if res==0:
            res=7
        print(dd[res])
    else:
        rday=0
        if pd(y):
            for j in range(1,m):
                rday+=rc[j]
        else:
            for j in range(1,m):
                rday+=c[j]
        rday+=d-1
        if pd(y):
            day+=366-rday
        else:
            day+=365-rday
        tem=(-(y+1))//4+(-(y+1))//400-(-(y+1))//100
        day+=(-(y+1)-tem)*365+tem*366
        res=abs(day)%7
        res=6-res
        if res==0:
            res=7
        print(dd[res])

0814:网线主管

描述

仙境的居民们决定举办一场程序设计区域赛。裁判委员会完全由自愿组成,他们承诺要组织一次史上最公正的比赛。他们决定将选手的电脑用星形拓扑结构连接在一起,即将它们全部连到一个单一的中心服务器。为了组织这个完全公正的比赛,裁判委员会主席提出要将所有选手的电脑等距离地围绕在服务器周围放置。

为购买网线,裁判委员会联系了当地的一个网络解决方案提供商,要求能够提供一定数量的等长网线。裁判委员会希望网线越长越好,这样选手们之间的距离可以尽可能远一些。

该公司的网线主管承接了这个任务。他知道库存中每条网线的长度(精确到厘米),并且只要告诉他所需的网线长度(精确到厘米),他都能够完成对网线的切割工作。但是,这次,所需的网线长度并不知道,这让网线主管不知所措。

你需要编写一个程序,帮助网线主管确定一个最长的网线长度,并且按此长度对库存中的网线进行切割,能够得到指定数量的网线。

输入

第一行包含两个整数N和K,以单个空格隔开。N(1 <= N <= 10000)是库存中的网线数,K(1 <= K <= 10000)是需要的网线数量。
接下来N行,每行一个数,为库存中每条网线的长度(单位:米)。所有网线的长度至少1m,至多100km。输入中的所有长度都精确到厘米,即保留到小数点后两位。

输出

网线主管能够从库存的网线中切出指定数量的网线的最长长度(单位:米)。必须精确到厘米,即保留到小数点后两位。
若无法得到长度至少为1cm的指定数量的网线,则必须输出“0.00”(不包含引号)。

样例输入

4 11
8.02
7.43
4.57
5.39

样例输出

2.00

Solution

还是二分,但是这道题的二分思路比较奇特?
也可能是我二分写少了,毕竟算法那边最近都在刷dp
就是,我们二分后存的答案可能是原来的答案,也可能是其他的,因为这道题跟上面的派不一样,这道题是1为离散的,那道题近似于连续
因此,我们最后取的时候,如果是存答案形式,要验证比它大1的时候可行,如果是直接取l,也要验证一下l是否可行,否则回退

def check(x):
    global ma,n,t
    cnt=0
    for length in ma:
        cnt+=length//x
    return cnt>=t

lst=input().split()
n=int(lst[0])
t=int(lst[1])
ma=[0]
mr=0
for i in range(1,n+1):
    k=float(input())
    temp=int(k*100)
    ma.append(temp)
    mr=max(mr,temp)
l=1
r=mr+1
while r>l:
    mid=(r+l)//2
    temp=0
    for i in range(1,n+1):
        temp+=ma[i]//mid
    if temp>=t:
        l=mid+1
    else:
        r=mid-1
if not check(l):
    l-=1
if l==0:
    print("0.00")
else:
    l=l/100
    print(f"{l:.2f}")

这样就差不多啦,明天希望能考个好成绩
接下来几天的目标:
1.完成一个lab
2.完成大作业的完善
3.搭建好自己的个人博客(疑似对外,到时候投简历有用)并把程设的内容搬过去,反正考完了,博客园这边更像自己写的随笔
4.装好archlinux双系统,虽然现在心里有点没底,这个显卡情况不要到时候把原生windows也一起搞坏就完蛋了(相信我们arch教以及二次元们的力量吧!)
5.(暑假)找学长要ICS的lab自己写写,离散、ICS跟数算的ppt看看,openjudge上写写数算题,然后还是打A

posted @ 2025-06-19 14:11  elainafan  阅读(7)  评论(0)    收藏  举报