题意
求有多少子数组的lcm为k.
以r为右端点, 左端点l取[1,r]可以得到r个lcm
这r个lcm按顺序一定是不增的, 相同的lcm的左端点是连续的.
考虑加入a[r+1]后, 满足lcm=k的左端点有多少.
这样其实不需要对左边的r个lcm去一一计算, 只需要从中计算不重复且为k的因子的那些
这样的lcm不会很多.
所以可以一直维护这个集合, 这样新加入一个数, 只需要和左边log级别的lcm运算求新增即可
在实现的时, 由于我们维护的Lcm集合不减, 且为k的因子, 所以每次只需要看第一个最大的lcm是否是k计算答案即可, 时间复杂度O(nlog(k) )
func gcd(a,b int) int{
if b==0{
return a
}
return gcd(b,a%b)
}
func subarrayLCM(nums []int, k int) int {
type result struct{
lcm int
i int
}
ans := 0
var a []result
i0 := -1
for i,x := range nums {
if k%x>0{
a = nil
i0 = i
continue
}
for j,p := range a{
a[j].lcm = p.lcm/gcd( p.lcm,x )*x
}
a = append( a,result{x,i} )
j := 0
for _,q := range a[1:]{
if a[j].lcm != q.lcm{
j++
a[j] = q
}else{
a[j].i = q.i
}
}
a = a[:j+1]
j = len( a )+1
for id,x := range a{
if x.lcm<=k{
j = id
break
}
}
a = a[j:]
if a[0].lcm == k{
ans += a[0].i-i0
}
}
return ans
}