between-two-sets

https://www.hackerrank.com/challenges/between-two-sets/problem?isFullScreen=true
最大公约数(Greatest Common Divisor, 简称 GCD) 是指两个或多个整数中,能同时整除它们的最大正整数。
欧几里得算法原理:
GCD(a,b)=GCD(b,a mod b)求最大公约数

int gcd(int a, int b) {

GCD
int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

最小公倍数是两个整数的 最小的公有倍数,也就是:能同时被两个数整除的最小正整数。
LCM(a,b)=(a*b)/GCD(a,b);

题目分析

  1. 每个 a 中的数都是 x 的因数(即 x 是 a 的倍数)→ 即:x % a[i] == 0 对所有 a[i]

条件1 ⇒ x 是数组 a 的 最小公倍数 L

  • 因为我们要求 x % a[i] == 0 对所有 a[i] 成立。
  • 最小满足这个条件的数是 a 的最小公倍数 L。
  • 所以:x 必须是 L 的倍数
    即:x ∈L,2L,3L...
  1. x 是每个 b 中数的因数(即 x 能整除所有 b)→ 即:b[i] % x == 0 对所有 b[i]

条件2 ⇒ x 是数组 b 的 最大公约数 G 的因数

  • 因为我们要求 b[i] % x == 0,对所有 b[i] 成立。
  • 也就是 x 能整除所有 b[i]。
  • 所以:x 必须是 G 的因数。
    即:x ∈ 所有能整除 G 的数

所以最终目标是:
找出那些 既是 L 的倍数、又是 G 的因数的数 x
L≤x≤G,x%L0,G%x0

目标 ``` int count = 0; for (int x = l; x <= g; x += l) { // x 是 L 的倍数 if (g % x == 0) { // x 也是 G 的因数 count++; // 满足两个条件 } } ```

为什么从 l开始,每次加 l,到 g?
因为:

  1. 我们只需要检查 L 的倍数(L, 2L, 3L...)
  • 因为其它不是 L 的倍数的数,一定不满足 “被所有 a[i] 整除” 条件。
  1. 终止于 G,是因为 x 不可能大于 G
  • 因为 x 还必须整除 G,所以不能大于它。
  1. 所以:
  • 我们只枚举 x = L, 2L, 3L, ..., G 的形式;
  • 然后判断这些数中,有多少能整除 G(即 G % x == 0)

答案

点击查看代码
int gcd(int a,int b)
{
    while(b!=0)
    {
        int t=b;
        b=a%b;
        a=t;
    }
    return a;
}
int lcm(int a,int b)
{
    return (a*b)/(gcd(a,b));
}
int getTotalX(vector<int> a, vector<int> b) {
    int r1=a[0];
    set<int>s;
    for(int i=1;i<a.size();++i)
    {
        r1=lcm(r1,a[i]);
    }
    int r2=b[0];
    int count=0;
    for(int i=1;i<b.size();++i)
    {
        r2=gcd(r2,b[i]);
    }
    
    for(int i=r1;i<=r2;i+=r1)
    {
        if(r2%i==0)
        {
            count++;
        }
    }
    return count;
}
posted @ 2025-07-02 10:14  哒哒DaDa^_^  阅读(12)  评论(0)    收藏  举报