0
点赞
收藏
分享

微信扫一扫

力扣1819. 序列中不同最大公约数的数目

悄然丝语 2022-04-02 阅读 26

1819. 序列中不同最大公约数的数目
题解

给你一个由正整数组成的数组 nums 。

数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。

例如,序列 [4,6,16] 的最大公约数是 2 。
数组的一个 子序列 本质是一个序列,可以通过删除数组中的某些元素(或者不删除)得到。

例如,[2,5,10][1,2,1,2,4,1,5,10] 的一个子序列。
计算并返回 nums 的所有 非空 子序列中 不同 最大公约数的 数目 。

 

示例 1:


输入:nums = [6,10,3]
输出:5
解释:上图显示了所有的非空子序列与各自的最大公约数。
不同的最大公约数为 610321 。
示例 2:

输入:nums = [5,15,40,5,6]
输出:7
 

提示:

1 <= nums.length <= 105
1 <= nums[i] <= 2 * 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-different-subsequences-gcds
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1、不可能枚举每个子序列,再从子序列中求最大公约数
2、转换角度,假设最大公约数为x,判断是否满足题目中的条件(PS:发现好多困难题目的做法都是这样,正着做做不出来,得反着来从结果的角度想
3、最大公约数的枚举范围为1到m,m为最大数值
4、检查此时x是否为子序列的最大公约数
5、方法:
a、最大公约数只能存在它的倍数中这个很容易理解,因此遍历的部分只是当前倍数存在于数组的数
b、这样的子序列中数字越多,最大公约数越小;反之也成立。原因是当前子序列中的数字必定大于x,因为都是x的倍数。假设4,8,最大公约数为4,增加一个数字6,最大公约数变为2,说明2的倍数越多时,最大公约数只会变小,不会变大,因此2此时就是这样的子序列的最小公约数。
c、利用这个特性,选取所有的x的倍数,求他们的最大公约数,不断地增加数目,gcd(a,b,c) = gcd(gcd(a,b),c),此时得到的最大公约数如果等于x,那么x就为所求(为什么一定要选所有的倍数?因为假如我们只选取其中的几个,此时由于规律b,最大公约数只会变大,又因为我们枚举可能的答案时是从小往大的,因此较大的公约数会在后面的枚举中出现

class Solution {
public:
    bool f[200001];
    int mx;
    int gcd(int a,int b){
        return b != 0?gcd(b,a % b):a;
    }
    bool check(int x){
        int t = 0;
        for(int i = x;i <= mx;i += x){
            if(f[i]){
                if(t == 0)t = i;
                else t = gcd(t,i);
            }
        }
        return t == x;
    }
    int countDifferentSubsequenceGCDs(vector<int>& nums) {
        memset(f,false,sizeof(f));
        for(int i = 0;i < nums.size();++i){
            f[nums[i]] = true;
        }
        mx = *max_element(nums.begin(),nums.end());
        int ans = 0;
        for(int i = 1;i <= mx;++i){
            if(check(i)){
                ans++;
            }
        }
        return ans;
    }
};
举报

相关推荐

0 条评论