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);
题目分析
- 每个 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...
- 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?
因为:
- 我们只需要检查 L 的倍数(L, 2L, 3L...)
- 因为其它不是 L 的倍数的数,一定不满足 “被所有 a[i] 整除” 条件。
- 终止于 G,是因为 x 不可能大于 G
- 因为 x 还必须整除 G,所以不能大于它。
- 所以:
- 我们只枚举 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;
}

浙公网安备 33010602011771号