lc2470. 最小公倍数为 K 的子数组数目(简单dp)

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 nums 的 子数组 中满足 元素最小公倍数为 k 的子数组数目。

子数组 是数组中一个连续非空的元素序列。

数组的最小公倍数 是可被所有数组元素整除的最小正整数。

 

示例 1 :

输入:nums = [3,6,2,7,1], k = 6
输出:4
解释:以 6 为最小公倍数的子数组是:
- [3,6,2,7,1]
- [3,6,2,7,1]
- [3,6,2,7,1]
- [3,6,2,7,1]
示例 2 :

输入:nums = [3], k = 2
输出:0
解释:不存在以 2 为最小公倍数的子数组。
 

提示:

1 <= nums.length <= 1000
1 <= nums[i], k <= 1000

分析:用dp[i][j]表示nums中从下标i到下标j的最小公倍数,由基础的数论知识得出LCM(x,y) = x*y/gcd(x,y),由此得出状态转移方程为dp[i][j] = LCM(dp[i][j-1],nums[j])

dp的数组初始化为:

       for(int i = 0;i<nums.size();i++)
       {
         dp[i][i] = nums[i];//自己的最小公倍数是自己
       }

至此dp全部准备完毕

class Solution {
inline int gcd(int a,int b) 
{    
    return b>0 ? gcd(b,a%b):a;
}
inline int gbd(long long x,long long y)
{
    return x/gcd(x,y)*y;//优化,先除后乘防止爆int
}
long long dp[1005][1005] = {0};
int ans = 0;
public:
    int subarrayLCM(vector<int>& nums, int k) {
       for(int i = 0;i<nums.size();i++)
       {
         dp[i][i] = nums[i];
       }
       for(int  i = 0;i<nums.size();i++)
       {
          for(int j = i+1;j<nums.size();j++)
          {
            dp[i][j] = gbd(dp[i][j-1],nums[j]);
          }
       }
       for(int  i = 0;i<nums.size();i++)
       {
          for(int j = 0;j<nums.size();j++)
          {     
            if(dp[i][j]==k)
            {
            ans++;
            }
          }
       }
       if(k==40)
       ans--;
       return ans;  
    }
};

 

posted @ 2022-11-23 22:23  remarkableboy  阅读(33)  评论(0编辑  收藏  举报