这周没什么人写题解,那就我来写一下吧,不会排版xjb写的,大家xjb看一下就行了
a题
n=int(input()) res=0 while n%10!=0: n+=1 res+=1 print(res)末尾有0,那么就是整除10,一直自增直到整除10即可
b题 模运算
s=input() res=t=0 for i in s: t=(t*10+int(i))%9 if t==0: res+=1 print(res)删掉一个后缀,也就是检查所有的前缀形成的数字是否能整除9
讲不太来,可以去lc2575下面看一下
c题 构造
n,k=map(int,input().split()) res=[] ch=0 while k: if k==1: res+=[ch]*2 k-=1 else: l=0;r=n while l+1!=r: mid=(l+r)//2 if mid*(mid-1)//2>k: r=mid else: l=mid res+=[ch]*l k-=l*(l-1)//2 ch=(ch+1)%26 while len(res)<n: res+=[ch] ch=(ch+1)%26 print("".join([chr(ord("a")+i) for i in res]))
恰好有k个长度大于1的回文子串,这题我感觉我和大多数人的脑回路都不一样
填还是一样的,按abcd...循环着填就可以了,主要是要构造恰好k个
一个长度为x的字母完全相同子字符串,会有x(x-1)/2个大于1的回文串
直接贪心的每次都填最多的就可以了,每次二分找到这个最大值
d题 贪心
n,k=map(int,input().split()) arr=list(map(int,input().split())) d=[] for i in range(1,n): d.append(abs(arr[i]-arr[i-1])) d.sort() if d[-1]<k: print(1) elif d[-1]==k: print(0) else: res=0 for i in d: if i>k: res+=(i+k-1)//k-1 print(res)先把每相邻两项的差的绝对值拿出来放一起
如果最大值小于k,那么需要一次
如果最大值等于k,那么需要0次
如果最大值大于k,那么把所有大于k的项x取出来
如果恰好是k的倍数,那么中间需要分成x//k份,否则需要分成x//k+1份
合起来写就是(x+k-1)//k份
一个东西分成(x+k-1)//k份,那么就需要切(x+k-1)//k-1刀
e题 调和级数+dp
n=int(input()) a=list(map(int,input().split())) cnt=[0]*(2*10**5+1) for i in a: cnt[i]+=1 dp={} res=max(cnt) for i in range(1,2*10**5+1): if cnt[i]: for j in range(2*i,2*10**5+1,i): if cnt[j]: k=j//i if (i,k) not in dp: t=1 else: t=dp[(i,k)] res=max(res,t+1) dp[(j,k)]=t+1 print(res)首先需要知道一个知识点,从1到n,每次枚举他们的倍数,每个数一直枚举到大于n停下
总的复杂度是nlogn的,具体可以搜一下调和级数
也就是说如果n是1e5,那么枚举出他们的所有倍数大概需要枚举1e6次,n是1e6,那么就要枚举1e7次
要构成等比数列,一种公比是1,那么我们开头的时候计个数,然后把频率最大值当作初始答案
另一种公比是多少我们不知道,但是肯定大于1的,所以我们从1到2e5,每次枚举他们的倍数,就可以算出这个公比,然后用哈希表+元组dp即可
复杂度是严格的nlogn的
复杂度是严格的nlogn的
f题 离线回答+树状数组
from collections import deque,defaultdict class BIT: """单点修改,区间和查询""" __slots__ = "size", "bit", "tree" def __init__(self, n: int): self.size = n self.bit = n.bit_length() self.tree = [0]*(n+1) def add(self, index: int, delta: int) -> None: # index 必须大于0 while index <= self.size: self.tree[index]+=delta index += index & -index def _query(self, index: int) -> int: res = 0 while index > 0: res += self.tree[index] index -= index & -index return res def query(self, left: int, right: int) -> int: return self._query(right) - self._query(left - 1) n,q=map(int,input().split()) arr=[0]+list(map(int,input().split())) d=defaultdict(deque) for i in range(1,n+1): d[arr[i]].append(i) query=[[] for _ in range(n+1)] res=[0]*q bit=BIT(n+5) for i in range(q): l,r=map(int,input().split()) query[r].append((i,l)) for r in range(1,n+1): while r-d[arr[r]][0]>1: x=d[arr[r]].popleft() bit.add(x,1) while query[r]: i,l=query[r].pop() res[i]=bit.query(l,r) for i in res: if i: print("YES") else: print("NO")
给定一个数组,多次询问一个区间[l,r],问该区间是否有长度严格大于2的回文子序列
其实我们只需要求是否有长度为3的回文子序列即可,那么只要有一个数字,出现了两次,且这两次的间隔大于1即可
先预处理出每个数字的出现位置,分别放在一个队列里
然后离线回答,把回答按右端点排序
从小到大遍历下标,对于该下标的数,左侧如果有与他距离大于1且还没出队列的,那么就出队,树状数组单点+1
然后批量回答该右端点的问题,如果区间的和大于0,则就有这样的回文子序列
g题 双指针+树状数组
class BIT: """单点修改,区间和查询""" __slots__ = "size", "bit", "tree" def __init__(self, n: int): self.size = n self.bit = n.bit_length() self.tree = [0]*(n+1) def add(self, index: int, delta: int) -> None: # index 必须大于0 while index <= self.size: self.tree[index]+=delta index += index & -index def _query(self, index: int) -> int: res = 0 while index > 0: res += self.tree[index] index -= index & -index return res def query(self, left: int, right: int) -> int: return self._query(right) - self._query(left - 1) sz=10**6+1 n,k=map(int,input().split()) a=list(map(int,input().split())) bit=BIT(sz+5) tot=0 for i in range(n): tot+=bit.query(a[i]+1,sz+2) bit.add(a[i],1) if tot<k: print(0) exit() bit2=BIT(sz+5) res=0 l=r=0 while r<n: tot-=bit._query(a[r]-1)+bit2.query(a[r]+1,sz+2) bit.add(a[r],-1) while tot<k: tot+=bit._query(a[l]-1)+bit2.query(a[l]+1,sz+2) bit2.add(a[l],1) l+=1 res+=r-l+1 r+=1 print(res+1)
求有多少个区间,删除以后剩下的部分逆序数大于等于k
首先求出原区间的逆序数,如果小于k,则无解
然后使用双指针,对左指针左侧部分,和右指针右侧部分各维护一个值域树状数组,设为b1和b2
右指针r右移时 逆序数 = 逆序数 - b1中小于a[r]的个数 - b2中大于a[r]的个数
左指针l右移时 逆序数 = 逆序数 + b1中小于a[l]的个数 + b2中大于a[l]的个数
最后还要加上删除空区间的答案