数论补充 之 前后缀分解问题
文章目录
- [0,i-1] 和 [i+1,n-1] 共同作用
- 3334,数组的最大因子得分
- 238.除自身以外数组的乘积
对于前缀分解问题,我愿把它分为几个大问题:[0,i] 或 [i,n-1] 或 [l,r],或 [0,i-1] 和 [i+1,n-1] 共同作用的问题
一般都是求解区间的和,乘积,GCD,LCM
[0,i-1] 和 [i+1,n-1] 共同作用
3334,数组的最大因子得分
3334,数组的最大因子得分
思路分析:对于这题,首先我们得知道 GCD(a,b,c)= GCD(GCD(a,b),c), LCM(a,b,c) = LCM(LCM(a,b),c)
知道了上面的那个性质之后,我们就应该想到可以使用前后缀分解来完成这个题目,我们 只要记录 nums[i] 前面和后面的各自的前缀和后缀的 GCD 和 LCM 这样我们移除 nums[i] 之后的 GCD和 LCM 就分别是 pregcd[0:i-1] ,sufgcd[i+1,n-1] 以及 prelcm[0:i-1] , suflcm[i+1,n-1]
class Solution:
def maxScore(self, nums: List[int]) -> int:
# 至多移除1个元素,那么总共会有n+1种可能也就是101种可能而已
# 分别使用pregcd,prelcm,sufgcd,suflcm
n = len(nums)
# 注意这个区间的开长了,lcm(1,x)= x,gcd(0,x) = x
pregcd ,prelcm, sufgcd,suflcm = [0]*(n+1),[0]*(n)+[1],[0]*(n+1),[0]*(n)+[1]
# 先求解前缀的情况
def lcm(a,b):
return a*b // math.gcd(a,b)
for i in range(n):
pregcd[i] = math.gcd(nums[i],pregcd[i-1])
prelcm[i] = lcm(nums[i],prelcm[i-1])
for i in range(n-1,-1,-1):
sufgcd[i] = math.gcd(sufgcd[i+1],nums[i])
suflcm[i] = lcm(suflcm[i+1],nums[i])
# 不移除元素
ans = pregcd[n-1]*prelcm[n-1]
# 枚举移除元素
for i in range(n):
# 精髓在这
ans = max(ans,math.gcd(pregcd[i-1],sufgcd[i+1])*lcm(prelcm[i-1],suflcm[i+1]))
return ans
238.除自身以外数组的乘积
238.除自身以外数组的乘积
思路分析:还是采用前后缀分解的思路
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
# 相同的思路,采用前后缀分解来完成
# 关键点,我们会把数组开长一点,这样就不用单独处理,否则就得处理第一个元素
n = len(nums)
prec,sufc = [1]*(n+1),[1]*(n+1)
for i in range(n):
prec[i] = prec[i-1]*nums[i]
for i in range(n-1,-1,-1):
sufc[i] = sufc[i+1]*nums[i]
ans = [1]*n
for i in range(n):
ans[i] = prec[i-1]*sufc[i+1]
return ans