洛谷原题链接

这是一道关于求最小公倍数、最大公约数逆运算的一道题。

做这道题首先要会求最大公约数和最小公倍数 ,对吧……

题目要求解个数,我们来看一看条件:

50分做法:

我们从条件中很容易看出x的范围——大于等于a1并且小于等于b1,所以我们暴力枚举a1到b1,然后对于每个可能的答案按照条件进行判断

代码:

#include<bits/stdc++.h>
#define R register int 
using namespace std;
typedef long long ll; 
ll n,a0,a1,b0,b1,ans;
inline ll gcd(ll x,ll y){
    ll z;
    while(y){
        z=x%y;
        x=y;
        y=z;
    }
    return x;
}
int main(){
    ios::sync_with_stdio(0);
    cin>>n;
    for(R t=1;t<=n;++t){
        cin>>a0>>a1>>b0>>b1;
        ans=0;
        for(R i=a1;i<=b1;++i) if(gcd(i,a0)==a1 && i*b0/gcd(i,b0)==b1) ++ans;
        printf("%lld\n",ans);
    }
    return 0;
}

AC做法:

在讲AC做法之前,我先说两个需要知道的关于最大公约数和最小公倍数的结论。

最大公约数:如果gcd(x,y)=z,那么gcd(x/z,y/z)=1。这个大家应该都知道,就不细讲了。

最小公倍数:

   ①如果lcm(x,y)=z,那么gcd(z/y,z/x)=1。这个我们来证明一下:我们设lcm(x,y)=z,那么lcm(x,y)=x*y/gcd(x,y)=z,所以gcd(x,y)=x*y/z。由最大公约数结论可得,gcd(z/y,z/x)=1。

   ②如果y是x的公倍数,则x是y的因数,也就是y % x == 0。

由上面几条结论可得,x一定是b1的因数,而且x % a1 == 0,gcd(x/a1 ,a0/a1) == 1,gcd(b1/b0 ,b1/x) == 1。

那么我们就可以枚举b1的因数,然后判断了。

代码:

#include<bits/stdc++.h>
#define R register int 
using namespace std;
int n,a0,a1,b0,b1,ans;
inline int gcd(int x,int y){
    if(!x) return y;
    if(!y) return x;
    R i,j;
    for(i = 0; !(x & 1); ++i) x >>= 1;
    for(j = 0; !(y & 1); ++j) y >>= 1;
    if(j < i) i = j;
    for(;;){
        if(x < y)  x ^= y,y ^= x,x ^= y;
        if(0 == (x %= y)) return y << i;
        while(!(x & 1)) x>>=1;
    } 
}
int main(){
    ios::sync_with_stdio(0);
    cin>>n;
    for(R t=1;t<=n;++t){
        cin>>a0>>a1>>b0>>b1;
        int p=a0/a1,q=b1/b0;
        ans=0;
        for(R x=1;x*x<=b1;++x)
          if(b1%x==0){
              if(x % a1 == 0 && gcd(x/a1,p)==1 && gcd(b1/x,q)==1) ++ans;
              int y=b1/x;
              if(x==y) continue;
              if(y % a1 ==0 && gcd(y/a1,p)==1 && gcd(b1/y,q)==1) ++ans;
          }
        printf("%d\n",ans);
    }
    return 0;
}