题目来源:牛客,拼多多2021笔试真题集
第一题:多多的数字组合
打卡题,很明显的两个约束:每个位数各不相同 + 数字最小,在这两个条件的约束下,N最大为45,对应的数字为123456789
。
代码如下:
def main():
N = int(input())
if N>45:
print(-1)
else:
ind = 9 # 指示当前添加到那个数字了
ans = ''
while N>ind:
ans = str(ind)+ans
N -= ind
ind -= 1
ans = str(N)+ans
print(ans)
return
if __name__ == '__main__':
main()
第二题:多多的字符变换
题目未限制操作次数,因此,相邻两字符的交换 等价于 任意两字符的交换,其代价都为0。
因此,想法是,字典存储每个字符串包含的字母对应的个数,去掉共同字符,剩下的字符从小到大排列,对应位置相减再求和即是答案。
注意,不能将剩下的字符求和再做相减,否则会发生抵消。
代码如下:
def main():
N = int(input())
X = input()
Y = input()
X_list,Y_list = [0]*26,[0]*26
for i in range(N):
X_list[ord(X[i])-97]+=1
Y_list[ord(Y[i])-97]+=1
X_sub,Y_sub = '',''
for i in range(26):
ind = min(X_list[i],Y_list[i])
X_sub += chr(i+97)*(X_list[i]-ind)
Y_sub += chr(i+97)*(Y_list[i]-ind)
ans = 0
for i in range(len(X_sub)):
ans += abs(ord(X_sub[i])-ord(Y_sub[i]))
print(ans)
return
if __name__ == '__main__':
main()
第三题:多多的求和计算
假设区间[i,j]的和谐值之和可以被M整除,并记作nM,同时,区间[0,i]的和谐值之和记作S1,区间[0,j]的和谐值之和记作S2,很显然,S2=S1+nM
,变换得到S2%M = S1%M
。这就是解题的关键:先求一遍前缀和,并对每个前缀和求余,记录余数为r的区间个数,再计算Cn2即可得到答案。
注意,答案需要加上前缀和自身对M求余为0的区间个数。
代码如下:
def main():
N,M = map(int,input().split())
cumu,ans = 0,0
rest = [0]*M
for i in input().split():
cumu += int(i)
rest[cumu%M]+=1
for i in rest:
ans += i*(i-1)//2
print(ans+rest[0])
return
if __name__ == '__main__':
main()
!!!太经典的题了,需要反复看,和谐值本身不需要被记录,所有的前缀和也不需要都被记录下来