史上最详细讲解P503 最大公约数和最小公倍数问题(NOI2001真题改编)


这道题其实是NOI2001的一道真题 改编,第一是多组数据,第二是时间复杂度要求较高。

一,暴力

每组数据直接2层循环,第一层枚举P,第二层枚举Q,如果满足条件就ans++,最后输出ans即可。

这里虽然是暴力,但是用了一点优化:

1.求a,b最小公倍数时可以直接a * b  / (a和b的最大公约数)

2.因为最小公倍数%最大公约数一定 == 0,不等于0说明一定不能当最小公倍数和最大公约数

代码:

#include<bits/stdc++.h>
long long a,b,ans,i,j,t;
long long f1(long long a,long long b)
{
  return a % b == 0 ? b : f1(b,a % b);
}
int main()
{
  while(~scanf("%lld%lld",&a,&b))
  {
    if(b % a)
    {
      printf("0\n");
      continue;
    }
    ans = 0;
    for(i = a; i <= b; i++)
    {
      for(int j = a;j <= b;j++)
      {
        t = f1(i,j);
        if(a == t && b == ((i * j) / t)) ans++;
	  }
    }
    printf("%lld\n",ans);
  }
  return 0;
}

 时间复杂度:O(logN * N^2 * 数据组数)


 ,优化掉一层循环

根据a * b = (a与b的最大公约数)  * (a与b的最小公倍数),我们可以只枚举P,那么Q=输入的2数的积 / P,这样,我们就可以省去一层循环。

时间复杂度:O(log N * N * 数据组数)

代码:

#include<bits/stdc++.h>
long long a,b,ans,i,j,t;
long long f1(long long a,long long b)
{
  return a % b == 0 ? b : f1(b,a % b);
}
int main()
{
  while(~scanf("%lld%lld",&a,&b))
  {
    if(b % a)
    {
      printf("0\n");
      continue;
    }
    ans = 0;
    for(i = a; i <= b; i++)
    {
      j = a * b / i;
      t = f1(i,j);
      if(a == t && b == ((i * j) / t)) ans++;
    }
    printf("%lld\n",ans);
  }
  return 0;
}


三,正解

#include<bits/stdc++.h>
long long a,b,ans,i,j,t;
int main()
{
  while(~scanf("%lld%lld",&a,&b))
  {
    if(b % a)
    {
      printf("0\n");
      continue;
    }
    ans = 0;
    b /= a;
    for(i = 2; i * i <= b; i++)
      if(b % i == 0)
      {
        ans++;
        while(b % i == 0) b /= i;
      }
    printf("%lld\n",1<<(ans + (b > 1)));
  }
  return 0;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值