洛谷1072 Hankson 的趣味题(素数)

版权声明:本文为博主原创文章,未经博主允许不得转载,除非先点了赞。 https://blog.csdn.net/A_Bright_CH/article/details/83063396

题意

求gcd(a0,x)=a1且lcm(b0,x)=b1中x的解的方案数。

题解

这种gcd的问题一般都要拆成质因数来分析。
线筛出1~sqrt(2e9)中的素数,那么所有数的质因数一定在其中出现,不然它本身就是一个素数(这个要特判)。
对于质数p,他们的次数分别为ca0,ca1,cb0,cb1。
分析gcd的特点,因为gcd(a0,x)=a1,所以有min(ca0,x)=ca1。具体情况如下:
1、ca0<ca1,无解
2、ca0=ca1,cx>=ca0
3、ca0>ca1,cx=ca1
同理分析lcm,因为lcm(b0,x)=b1,所以max(cb0,x)=cb1。具体分析:
1、cb0>cb1,无解
2、cb0=cb1,cx<cb0
3、cb0<cb1,cx=cb1
结合两者的情况,会有
1、ca0<cb0 或 cb0>cb1,无解
2、ca0=ca1 且 cb0=cb1,若同时有ca0<=cb0,则cx有cb0-ca0+1个取值方案
3、ca0=ca1 且 cb0<cb1,若同时有ca0<=cb1,则cx有1个取值方案
4、ca0>ca1 且 cb0=cb1,若同时有ca1<=cb0,则cx有1个取值方案
5、ca0>ca1 且 cb0<cb1,若同时有ca1=cb1,则cx有1个取值方案
好了,有了这些就可以打代码了,ans等于所有质因数中的取值方案累乘。

代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=2010;
int tot=0,prime[40000];
int v[50000];
void getprime(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(v[i]==0)
        {
            v[i]=i;
            prime[++tot]=i;
        }
        for(int j=1;j<=tot;j++)
        {
            if(prime[j]*i>n || v[i]<prime[j]) break;
            v[prime[j]*i]=prime[j];
        }
    }
}

void get(int &x,int &cnt,int p)
{
    while(x%p==0)
    {
        x/=p;cnt++;
    }
}

int main()
{
    getprime(sqrt(2e9)+10);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int a0,a1,b0,b1;
        scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
        int ca0,ca1,cb0,cb1;
        int ans=1,cnt;
        for(int i=1;i<=tot;i++)
        {
            ca0=ca1=cb0=cb1=0;
            get(a0,ca0,prime[i]);get(a1,ca1,prime[i]);
            get(b0,cb0,prime[i]);get(b1,cb1,prime[i]);
            if(ca0==ca1 && cb0==cb1 && ca0<=cb0) cnt=cb0-ca0+1;
            else if(ca0==ca1 && cb0<cb1 && ca0<=cb1) cnt=1;
            else if(ca0>ca1 && cb0==cb1 && ca1<=cb0) cnt=1;
            else if(ca0>ca1 && cb0<cb1 && ca1==cb1) cnt=1;
            else{ans=0;break;}
            ans*=cnt;
        }
        if(ans!=0)//如果其本身不为1,说明其本身是素数 
        {
recheck:    int p;
            if(a0!=1){p=a0;goto begin;}
            if(a1!=1){p=a1;;goto begin;}
            if(b0!=1){p=b0;goto begin;}
            if(b1!=1){p=b1;goto begin;}
            goto end;
begin:      ca0=ca1=cb0=cb1=0;
            get(a0,ca0,p);get(a1,ca1,p);
            get(b0,cb0,p);get(b1,cb1,p);
            if(ca0==ca1 && cb0==cb1 && ca0<=cb0) cnt=cb0-ca0+1;
            else if(ca0==ca1 && cb0<cb1 && ca0<=cb1) cnt=1;
            else if(ca0>ca1 && cb0==cb1 && ca1<=cb0) cnt=1;
            else if(ca0>ca1 && cb0<cb1 && ca1==cb1) cnt=1;
            else{ans=0;break;}
            ans*=cnt;
            goto recheck;
        }
//      printf("(%lld %lld %lld %lld)\n",a0,a1,b0,b1);
end:    printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/A_Bright_CH/article/details/83063396