A:出现次数能被 K 整除的元素总和
签到题,给一个整数数组nums和一个数k,计算nums中出现次数能被k整除的数之和。
解法,做一个cnt,再遍历一遍就行了。

1 class Solution: 2 def sumDivisibleByK(self, nums: List[int], k: int) -> int: 3 d=defaultdict() 4 for x in nums: 5 if x in d: 6 d[x]+=1 7 else: 8 d[x]=1 9 res=0 10 for x,v in d.items(): 11 if v%k==0: 12 res+=x*v 13 return res
B:最长的平衡子串 I
给定一个字符串s,求平衡子串的个数。平衡子串为串内出现的字母的出现次数都是相等的。
解法,因为s的长度最多为1000,那么可以直接枚举l和r,然后再做一个26的判定。时间复杂度为O(26*n^2)。

1 class Solution: 2 def longestBalanced(self, s: str) -> int: 3 n=len(s) 4 res=0 5 for i in range(n): 6 cnt=[0]*26 7 for j in range(i,n): 8 cnt[ord(s[j])-ord('a')]+=1 9 minn,maxx=1010,0 10 for k in range(26): 11 if cnt[k]!=0: 12 minn=min(minn,cnt[k]) 13 maxx=max(maxx,cnt[k]) 14 if minn==maxx and maxx!=0: 15 res=max(res,j-i+1) 16 return res
C:最长的平衡子串 II
题意整体同B,但是s中只有'a','b','c'三种字符,且字符串长度到了1e5。
解法,那么如此就不能用平方级的解法了,因为字符种类变少了,那么合法的字符串只有可能是以下几种形式。全部由"a"、"b"、"c"、"a""b"、"a""c"、"b""c"、"a""b""c"组成。
单个字符的话,我们直接用最长连续就能计算。
现在我们考虑a,b,c都出现的情况,s的L~R的a,b,c三个字符出现次数相等,也就意味着suma[r]-suma[l-1]==sumb[r]-sumb[l-1]==sumc[r]-sumc[l-1],推导一下,能将后面的三种情况统一起来。
s表示sum,sa[r]-sb[r]==sa[l-1]-sb[l-1] && sa[r]-sc[r]==sa[l-1]-sc[l-1]。便于在遍历时维护,同时用上枚举右、维护左的方法。

1 class Solution: 2 def longestBalanced(self, s: str) -> int: 3 res=0 4 for key,group in groupby(s): 5 res=max(res,len(list(group))) 6 d_ABC=defaultdict() 7 d_AB_C=defaultdict() 8 d_AC_B=defaultdict() 9 d_BC_A=defaultdict() 10 d_ABC[(0,0)]=-1 11 d_AB_C[(0,0)]=-1 12 d_AC_B[(0,0)]=-1 13 d_BC_A[(0,0)]=-1 14 A,B,C=0,0,0 15 for i,c in enumerate(s): 16 if c=='a': 17 A+=1 18 elif c=='b': 19 B+=1 20 else: 21 C+=1 22 # abc都有 23 if (A-B,A-C) in d_ABC: 24 res=max(res,i-d_ABC[(A-B,A-C)]) 25 else: 26 d_ABC[(A-B,A-C)]=i 27 # 只有ab 28 if (A-B,C) in d_AB_C: 29 res=max(res,i-d_AB_C[(A-B,C)]) 30 else: 31 d_AB_C[(A-B,C)]=i 32 33 if (A-C,B) in d_AC_B: 34 res=max(res,i-d_AC_B[(A-C,B)]) 35 else: 36 d_AC_B[(A-C,B)]=i 37 38 if (B-C,A) in d_BC_A: 39 res=max(res,i-d_BC_A[(B-C,A)]) 40 else: 41 d_BC_A[(B-C,A)]=i 42 return res
D:完全平方数的祖先个数总和
给一棵数,节点上有值,当前节点和祖先相乘得到的数如果是完全平方数,则匹配,问有多少匹配的对数。
解法,两个数相乘是否是完全平方数,取决于他们去除冗余之后是否相等。去除冗余:x=360=2^3*3^2*5,去除冗余即为去除平方的项,x_kernel=2*5=10,那么如果y_kernel==10,那么他们就匹配。
所以,我们把nums去除冗余之后,再做一遍dfs的同时维护走过的节点的值出现次数即可。

1 class Solution: 2 def sumOfAncestors(self, n: int, edges: List[List[int]], nums: List[int]) -> int: 3 def fun(x): 4 res=1 5 for i in range(2,isqrt(x)+1): 6 s=0 7 while x%i==0: 8 x//=i 9 s+=1 10 if s%2==1: 11 res*=i 12 if x>1: 13 res*=x 14 return res 15 # 将偶数次幂去掉 16 for i in range(n): 17 nums[i]=fun(nums[i]) 18 # print(nums) 19 g=[[] for i in range(n)] 20 for [u,v] in edges: 21 g[u].append(v) 22 g[v].append(u) 23 cnt=defaultdict() 24 res=0 25 def dfs(fa,u): 26 nonlocal res 27 if nums[u] in cnt: 28 res+=cnt[nums[u]] 29 cnt[nums[u]]+=1 30 else: 31 cnt[nums[u]]=1 32 for v in g[u]: 33 if v==fa: 34 continue 35 dfs(u,v) 36 cnt[nums[u]]-=1 37 dfs(-1,0) 38 return res