Hankson的趣味题

· · 题解

传送门:hankson的趣味 (毒瘤)

gcd(a,b)=p_1^{min(r_1,t_1)}p_2^{min(r_2,t_2)}...p_s^{min(r_s,t_s)} lcm(a,b)=p_1^{max(r_1,t_1)}p_2^{max(r_2,t_2)}...p_s^{max(r_s,t_s)}

根据以上两个式子,我们可以对a_0,a_1,b_0,b_1进行质因数分解,对每一个p_i分别将其指数记录为num_{a_0},num_{a_1},num_{b_0},num_{b_1};记录x在p_i的指数上能有几种情况;

所以,一个素数表是必不可少的。

然后就是质因数分解啦。

分别记录gcd,lcm公共的种数情况;

接下来分类讨论:

- 如果$num_{a_0}<num_{a_1}$ --> 0种 - 如果$num_{b_0}>num_{b_1}$ --> 0种 - 如果$gcd=lcm=1
 ①$num_{a_1}=num_{b_1}$ --> 1种

 ②$num_{a_1}>num_{b_1}$ --> 0种

emmm,其实我也不知道对不对。

\mathfrak {Code}:

#include<bits/stdc++.h>
using namespace std;
const int N=50000;
int prime[N],tot;
bool vis[N];

void getprime()
{
    for(int i=2;i<=50000;i++){
        if(!vis[i]){
            prime[++tot]=i;
        }
        for(int j=1;j<=tot&&i*prime[j]<=50000;j++){
            vis[i*prime[j]]=true;
            if(i%prime[j]==0){
                break;
            }
        }
    }
}

int work(){
    int ans=1;
    int a,aa,b,bb;
    cin>>a>>aa>>b>>bb;
    if(a<aa||b>bb){
        return 0;
    }
    for(int i=1;i<=tot&&prime[i]<=bb;i++){ 
        int numa=0,numaa=0,numb=0,numbb=0;
        int qcda=1e9,lcmb=1;
        int x=prime[i];
        while(a%x==0){a/=x;numa++;}
        while(aa%x==0){aa/=x;numaa++;}
        while(b%x==0){b/=x;numb++;}
        while(bb%x==0){bb/=x;numbb++;}
        int m;
        if(numa<numaa||numb>numbb){
            return 0;
        }
        if(numa>numaa)qcda=1;
        if(numa==numaa)qcda=1e9;
        if(numb==numbb)lcmb=numbb+1;
        if(numb<numbb)lcmb=1;
        if(numaa>numbb){
            return 0;
        }
        if(lcmb==1&&qcda==1){//都是一种 
            if(numaa==numbb){//如果相同 
                m=1;//就为一种 
            }
            else{//如果不同,0种
                return 0;
            }
        }
        else if(lcmb>qcda){//如果lcm多种,qcd为1种;
        /*因为numbb>=numaa,所以qcd一定是lcm的子集,即m=1*/ 
            m=qcda;
        }
        else if(qcda==1e9&&lcmb>1){//如果qcd为无限种;
        /*例如:qcd中要保证>=6,lcm中要保证<=7,m应该为7-6+1,即2*/ 
            m=numbb-numaa+1;
        }
        else if(lcmb==1&&qcda==1e9){
            m=1;
        }
        ans*=m;
    }
    if(b==bb&&bb!=1&&b!=a&&b!=aa)ans*=2;
    return ans;
}

int main()
{
    getprime();
    int T;
    cin>>T;
    while(T--){
        cout<<work()<<endl;
    }

}