Codeforces Round #489 (Div. 2) ---- B. Nastya Studies Informatics (数学)

题目链接:http://codeforces.com/contest/992/problem/B

题意: 给你一个范围[l,r],和x,y,让你求在范围内,满足gcd(a,b) = x,lcm(a,b) = y的数对(a,b)有多少个。

思路: 普通人的枚举思路是过不了啊QAQ(来自超霸的藐视)
所以在超霸的讲解下,要懂得缩小枚举范围~ QVQ
首先,我们根据gcd和lcm的关系,可以推出 a*b = x*y
然后我们两边同时除以x ,得 a*b/(x) = y,然后我们可以转换一下,a = p*x, b = q*x,即
a是x的p倍,b是x的q倍,那么p,q一定互质,即gcd(p,q) = 1 。如果不理解为什么,那么这样写
gcd(a,b) = gcd(px,qx) = x 酱紫就知道 为什么 gcd(p,q) = 1啦~~

然后我们把上式转换 为 p*q*x^2 /(x)= y —> p*q = y/x
酱紫枚举范围就缩小到了sqrt(y/x) 从1e9 —> 1e5

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
int main()
{
    #ifdef LOCAL_FILE
    freopen("in.txt","r",stdin);
    #endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
    int sum = 0;
    int l,r,x,y;
    cin>>l>>r>>x>>y;
    if(y%x)
    {
        printf("0\n");
        return 0;
    }
    y/=x;
    for(int i=1;i<=sqrt(y+0.5);i++)
    {
        if(y%i) continue;
        if(i*x>=l && y/i*x<=r && gcd(y/i,i) == 1)
        {
            sum+=2;
            if(y/i == i)
                sum--;
        }
    }
    cout<<sum<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37624640/article/details/80737428