3901.好子序列查询
难度:困难
问题描述:
给你一个长度为n的整数数组nums和一个整数p。
如果nums的一个非空子序列满足以下条件,则称其为好子序列:
其长度严格小于n。
其所有元素的最大公约数(GCD)恰好等于p。
另给定一个长度为q的二维整数数组queries,其中queries[i]=[indi,vali]表示你需要将nums[indi]更新为vali。
在每次查询更新后,判断当前数组中是否存在任意一个好子序列。
返回一个整数,表示在多少次查询之后,数组中存在好子序列。
子序列是指通过删除原序列中的某些元素或不删除任何元素,并且不改变剩余元素相对顺序后得到的序列。
gcd(a,b)表示a和b的最大公约数。
示例1:
输入:nums=[4,8,12,16],p=2,queries=[[0,3],[2,6]]
输出:1
解释:
i [indi,vali] 操作 更新后的nums 是否存在好子序列
0 [0,3] 将nums[0]更新为3 [3,8,12,16] 否,因为不存在最大公约数恰好为p=2的子序列
1 [2,6] 将nums[2]更新为6 [3,8,6,16] 是,子序列[8,6]的最大公约数恰好为p=2
因此,答案是1。
示例2:
输入:nums=[4,5,7,8],p=3,queries=[[0,6],[1,9],[2,3]]
输出:2
解释:
i [indi,vali] 操作 更新后的nums 是否存在好子序列
0 [0,6] 将nums[0]更新为6 [6,5,7,8] 否,因为不存在最大公约数恰好为p=3的子序列
1 [1,9] 将nums[1]更新为9 [6,9,7,8] 是,子序列[6,9]的最大公约数恰好为p=3
2 [2,3] 将nums[2]更新为3 [6,9,3,8] 是,子序列[6,9,3]的最大公约数恰好为p=3
因此,答案是2。
示例3:
输入:nums=[5,7,9],p=2,queries=[[1,4],[2,8]]
输出:0
解释:
i [indi,vali] 操作 更新后的nums 是否存在好子序列
0 [1,4] 将nums[1]更新为4 [5,4,9] 否,因为不存在最大公约数恰好为p=2的子序列
1 [2,8] 将nums[2]更新为8 [5,4,8] 否,因为不存在最大公约数恰好为p=2的子序列
因此,答案是0。
提示:
2<=n==nums.length<=5*104
1<=nums[i]<=5*104
1<=queries.length<=5*104
queries[i]=[indi,vali]
1<=vali,p<=5*104
0<=indi<=n-1
问题分析:
为解决本问题,第一个要解决的是如何求出多个整数的最大公约数,为此设计函数my_gcd(a),其功能是对于一个列表a,求出其中所有元素的最大公约数并返回;其次是判断一个序列是否为一个好序列,为此设计函数check_a_good_sub_array(a,p),用于判断一个列表a是否存在有一个子序列,其最大公约数为p,如果存在,则a是好序列,返回True,否则返回False,在具体处理的时候,不需要把a的所有子序列都找出来,而是把a中所有能被p整除的元素按顺序找出,并重新生成一个列表,然后对这个列表进行处理,这样会签单得多;最后在主程序中按queries列表中的操作依次进行处理,统计好子序列数并输出,问题得到解决。
程序如下:
python
from math import gcd
#计算一个列表中所有元素的最大公约数并返回
def my_gcd(a):
n=len(a)
if n==2:
return gcd(a[0],a[1])
else:
return gcd(a[0],my_gcd(a[1:n]))
#判断一个列表是否为一个好序列,如果是返回True,否则返回False
def check_a_good_sub_array(a,p):
n=len(a)
t=[]
for i in a:
if i%p==0:
t.append(i)
m=len(t)
if m<2:
return False,[]
else:
for i in range(0,m-1):
for j in range(i+2,m+1):
b=t[i:j]
c=my_gcd(b)
if c==1:
break
elif c==p and len(b)!=n:
return True,b
else:
continue
else:
return False,[]
#主程序
nums=eval(input('pls input nums='))
p=int(input('pls input p='))
queries=eval(input('pls input queries='))
n=len(nums)
c=0
for i in queries:
print('操作:',i,end=' ')
nums[i[0]]=i[1]
print('操作后的nums为:',nums,end=' ' )
flag,t=check_a_good_sub_array(nums,p)
if flag:
print(f'是,子序列({t})的最大公约数恰好为p={p}的子序列')
c+=1
else:
print(f'否,因为不存在最大公约数为p={p}的长度严格小于{n}子序列')
print(f'经过多次查询之后,存在的好子序列共有{c}个')
运行实例一
pls input nums=[3,5,7,1]
pls input p=3
pls input queries=[[2,9],[1,6]]
操作: [2, 9] 操作后的nums为: [3, 5, 9, 1] 是,子序列([3, 9])的最大公约数恰好为p=3的子序列
操作: [1, 6] 操作后的nums为: [3, 6, 9, 1] 是,子序列([3, 6])的最大公约数恰好为p=3的子序列
经过多次查询之后,存在的好子序列共有2个
运行实例二
pls input nums=[2,3,5,6]
pls input p=2
pls input queries=[[0,1],[2,4]]
操作: [0, 1] 操作后的nums为: [1, 3, 5, 6] 否,因为不存在最大公约数为p=2的子序列
操作: [2, 4] 操作后的nums为: [1, 3, 4, 6] 是,子序列([4, 6])的最大公约数恰好为p=2的子序列
经过多次查询之后,存在的好子序列共有1个
运行实例三
pls input nums=[2,3]
pls input p=3
pls input queries=[[0,6]]
操作: [0, 6] 操作后的nums为: [6, 3] 否,因为不存在最大公约数为p=3的长度严格小于2子序列
经过多次查询之后,存在的好子序列共有0个