C-填空题
题意
对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从 1900 年 1 月 1 日至 9999 年 12 月 31 日,总共有多少天,年份的数位数字之和等于月的数位数字之和加日的数位数字之和。
例如,2022年11月13日满足要求,因为 2+0+2+2=(1+1)+(1+3) 。请提交满足条件的日期的总数量。
答案
70910
import os
import sys
# 请在此输入您的代码
def num_sum(n):#数字求和
sum=0
while n>0:
sum=sum+n%10
n=n//10
return sum
count = 0
day = [0,31,28,31,30,31,30,31,31,30,31,30,31]
for y in range(1900,10000):
for m in range(1,13):
if (y%4==0 and y%100!=0 )or(y%400==0):#闰年2月单独考虑
day[2]=29
else:
day[2]=28
for d in range(1,day[m]+1):
if num_sum(y)==num_sum(m)+num_sum(d):
count+=1
print(count)
试题A:特殊日期 (5分)
【问题描述】
记一个日期为 yy 年 mm 月 dd 日,统计从 2000 年 1 月 1 日到 2000000 年 1 月 1 日:有多少个日期满足年份 yy 是月份 mm 的倍数,同时也是 dd 的倍数。
【答案】
35813063
count=1
day = [0,31,28,31,30,31,30,31,31,30,31,30,31]
for y in range(2000,2000000):
for m in range(1,13):
if (y % 4 == 0 and y % 100 != 0) or (y % 400 == 0): # 闰年2月单独考虑
day[2] = 29
else:
day[2] = 28
for d in range(1,day[m]+1):
if y%m==0 and y%d==0:
count+=1
print(count)
试题B:分糖果 (5分)
【问题描述】
两种糖果分别有9个和16个,要全部分给7个小朋友,每个小朋友得到的糖果总数最少为2个最多为5个,问有多少种不同的分法,糖果必须全部分完。
如果有其中一个小朋友在两种方案中分到的糖果不完全相同,这两种方案就算作不同的方案。【答案提交】
5067671
a=[0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5]
b=[2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0]
def divide(t,n1,n2):#第几个小朋友,目前剩下的a糖果数,目前剩下的b糖果数
global count
if t==8:
if n1==0 and n2==0:
count+=1
else:
return
else:
for i in range(len(a)):
if n1>=a[i] and n2>=b[i]:
divide(t+1,n1-a[i],n2-b[i])
count=0
divide(1,9,16)
print(count)
试题C:三国游戏 (10分)
【问题描述】
小蓝正在玩一款游戏,游戏中魏(X)、蜀(Y)、吴(Z)三个国家各自拥有一定数量的士兵X、Y、Z(一开始可以认为都是0)。游戏有n个可能会发送的事件,每个事件之间相互独立且最多只发送一次,当第i个事件发送时会分别让X、Y、Z增加 .
当游戏结束时(所以事件的发生与否已经确定),如果X,Y,Z的其中一个大于另外两个之和,我们认为其获胜。例如,当X>Y+Z时,我们认为魏国获胜,小蓝想知道游戏结束时,如果有其中一个国家获胜,最多发生了多少个事件?如果不存在任何一个让某个国家获胜的情况,请输出-1。
【输入格式】
输入的第一行包含一个整数n。
第二行包含n个整数表示A,相邻整数之间使用一个空格分隔
第三行包含n个整数表示B,相整数之间使用一个空格分隔
第四行包含n个整数表示C,相邻整数之间使用一个空格分隔【输出格式】
输出一行包括一个整数表示答案。
n=int(input())
aa=list(map(int,input().split()))#每次的事件
bb=list(map(int,input().split()))
cc=list(map(int,input().split()))
all_a=sorted([aa[i]-bb[i]-cc[i] for i in range(n)],reverse=True)#每次事件中a获胜的差
all_b=sorted([bb[i]-aa[i]-cc[i] for i in range(n)],reverse=True)#每次事件中b获胜的差
all_c=sorted([cc[i]-bb[i]-aa[i] for i in range(n)],reverse=True)#每次事件中c获胜的差
suma,sumb,sumc,counta,countb,countc=0,0,0,0,0,0
for i in range(n):
suma=suma+all_a[i]
if suma<=0:
break
else:
counta+=1
for i in range(n):
sumb=sumb+all_b[i]
if sumb<=0:
break
else:
countb+=1
for i in range(n):
sumc=sumc+all_c[i]
if sumc<=0:
break
else:
countc+=1
count=max(counta,countb,countc)
print(count if count else -1)
试题D:平均 (10分)
【问题描述】
有一个长度为n的数组(n是10的倍数),每个数a都是区间[0, 9]中的整数。小明发现数组里每种数出现的次数不太平均,而更改第i个数的代价为bi,他想更改若干个数的值使得这10种数出现的次数相等(都等于n/10),请问代价和最少为多少。
【输入格式】
输入的第一行包括一个正整数n。
接下来n行,第i行包括两个整数ai,bi,用一个空格分隔。【输出格式】
输出包括一个正整数表示答案。
n=int(input())
a=[[] for i in range(10)]
for i in range(n):
aa,bb=map(int,input().split())
a[aa].append(bb)
ave=n//10
count=0
for i in range(10):
if len(a[i])>ave:
a[i].sort(reverse=True)
for j in a[i][ave:]:
count=count+j
print(count)
试题E:翻转 (15分)
【问题描述】
小蓝用黑白棋的n个棋子排成了一行,他在脑海里想象出了一个长度为 n的01串T,他发现如果把黑棋当做1,白棋当做0,这一行棋子也是一个长度为n的01串S。
小蓝决定,如果在S中发现一个棋子和它两边的棋子都不一样,就可以将其翻转变成另一个颜色。也就是说,如果S中存在子串 101或者010,就可以选择将其分别变为111和000,这样的操作可以无限重复。
小蓝想知道最少翻转多少次可以把S变成和一模一样【输入格式】
输入包含多组数据
输入的第一行包含一个正整数 D表示数据组数
后面2D行每行包含一个01串,每两行为一组数据,第 2i-1行为第i组数据的Ti,第2i行为第i组数据的Si,Si和Ti度均为n。【输出格式】
对于每组数据,输出一行包含一个整数,表示答案,如果答案不存在请输出-1。
d=int(input())
for i in range(d):
t=list(input())
s = list(input())
count=0
flag=1
for j in range(len(s)):
if s[j]!=t[j]:
if j-1>=0 and j+1<len(s) and s[j]!=s[j-1] and s[j]!=s[j+1]:
s[j]=s[j-1]
count+=1
else:
flag=0
break
print(count if flag else -1)
注意:这道题最后if flag判断中,flag=0时才为false,flag=-1时为true!!!flag=-1表明flag有值不为空,所以是true
试题G:阶乘的和 (20分)
【问题描述】
给定n个数,问能满足m!为的因数的最大的m是多少,其中m!表示m的阶乘,即1x2x3x···xm。
【输入格式】
输入的第一行包含一个整数n。
第二行包含n个整数,分别表示,相邻整数之间使用一个空格分隔。【输出格式】
给出一行包括一个整数表示答案。
n=int(input())
a=list(map(int,input().split()))
a.sort()
st,i,cnt = a[0],0,0#st是当前数,i是循环次数
while i<n:
while i<n and a[i]==st:#count是当前的个数
cnt += 1
i += 1
if cnt and cnt%(st+1)==0:#可以向上转换
cnt,st = cnt//(st+1),st+1#上一级数st+1从cnt=1开始计数
else:#不能向上转换,当前数就是“m”
break
print(st)
思路:如果所有数都只出现一次,则m为min(Ai)。有(min(Ai)+1)个min(Ai)!,m才能变为min(Ai)+1,具体来说,有:3!+3!+3!+3!=4*3!==4!
print("方法二,但是没跑出来,可以掠过不看")
n=int(input())
a=list(map(int,input().split()))
l=dict()#字典储存
for i in a:
if i not in l:
l[i]=0#如果字典里没有i,创建一个i作为key
l[i]+=1#统计每个数的个数
flag=1
for i in sorted(l.keys()):#从小到大排
m=l[i]//(i+1)
n=l[i]%(i+1)
if n==0:#这个数可以向上转化一个阶乘
if i+1 not in l:
l[i+1]=0
l[i+1]+=m
del l[i]
else:#不能转换,这个数就是最大的“m”
flag=0
break
if flag==0:#不能转换情况下,直接输出i
print(i)
else:#可以转换情况下,此时key中只剩一个数
p=i+1#key
q=l[p]#value
while q>=p+1:
m = l[p] // (p + 1)
n = l[p] % (p + 1)
if n != 0:
break
l[p + 1] += m
del l[p]
for i in l.keys():
print(i)
试题I:子树的大小 (25分)
【问题描述】
给定一棵包含n个结点的完全m又树,结点按从根到叶、从左到右的顺序依次编号。例如下图是一个拥有 11个结点的完全3又树。
你需要求出第k个结点的子树的结点数。
【输入格式】
输入包含多组询问。
输入的第一行包含一个整数T,表示询问次数。
接下来行,每行包含三个整数 n,m,k,表示一组询问。【输出格式】
输出T行,每行包含一个整数表示对应询问的答案。
t=int(input())
for i in range(t):
n,m,k=map(int,input().split())
count=0#结点数
l=k#左指针
r=k#右指针
res=1#子树中的节点数
while True:
count+=res#先加上自己的节点数
if r*m+1>n:#超出节点范围
if (l-1)*m+2<=n:#最后一个节点在在k中
count+=n-((l-1)*m+1)#加上子树中的节点树
break
res*=m#每一层多3个节点
r=r*m+1#右侧的节点总数
l=(l-1)*m+2#左侧的节点总数
print(count)
注意:子树中自己也算一个节点,所以对于图中的k=4时,节点数为2