1. 程式人生 > >CH3201 Hankson的趣味題

CH3201 Hankson的趣味題

continue 分類討論 表示 幫助 mat get 就是 bit freopen

題意

描述

Hanks博士是BT(Bio-Tech,生物技術)領域的知名專家,他的兒子名叫Hankson。現在,剛剛放學回家的Hankson正在思考一個有趣的問題。
今天在課堂上,老師講解了如何求兩個正整數c1和c2的最大公約數和最小公倍數。現在Hankson認為自己已經熟練地掌握了這些知識,他開始思考一個“求公約數”和“求公倍數”之類問題的“逆問題”,這個問題是這樣的:已知正整數a0,a1,b0,b1,設某未知正整數x滿足:
1、 x和a0的最大公約數是a1;
2、 x和b0的最小公倍數是b1。
Hankson的“逆問題”就是求出滿足條件的正整數x。但稍加思索之後,他發現這樣的x並不唯一,甚至可能不存在。因此他轉而開始考慮如何求解滿足條件的x的個數。請你幫助他編程求解這個問題。

輸入格式

輸入第一行為一個正整數n,表示有n組輸入數據。接下來的n行每行一組輸入數據,為四個正整數a0,a1,b0,b1,每兩個整數之間用一個空格隔開。輸入數據保證a0能被a1整除,b1能被b0整除。

輸出格式

輸出共n行。每組輸入數據的輸出結果占一行,為一個整數。
對於每組數據:若不存在這樣的x,請輸出0;
若存在這樣的x,請輸出滿足條件的x的個數;

樣例輸入

2
41 1 96 288
95 1 37 1776

樣例輸出

6
2

數據範圍與約定

對於 50%的數據,保證有1≤a0,a1,b0,b1≤10000 且n≤100。
對於 100%的數據,保證有1≤a0,a1,b0,b1≤2,000,000,000 且n≤2000。

樣例解釋

第一組輸入數據, x x 可以是 9,18,36,72,144,2889,18,36,72,144,288 ,共有 66 個。

第二組輸入數據, xx 可以是 48,177648,1776 ,共有 22 個。

來源

CCF NOIP2009

分析

預處理出\(\sqrt{2\times 10^9}\)以內的質數,對每個質因數分類討論即可。

時間復雜度\(O(n \sqrt{d}/\log d)\)

代碼

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long ll;

co int N=1e5+6,INF=0x3f3f3f3f;
int p[N];
bool v[N];
int main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    v[1]=1;
    int tot=0;
    for(int i=2;i<=5e4;++i){
        if(!v[i]) p[++tot]=i;
        for(int j=1,k;j<=tot;++j){
            k=i*p[j];
            if(k>5e4) break;
            v[k]=1;
            if(i%p[j]==0) break;
        }
    }
    int n=read<int>();
    while(n--){
        int a0,a1,b0,b1;
        read(a0),read(a1),read(b0),read(b1);
        if(a1>a0||b1<b0){
            puts("0");
            continue;
        }
        int ans=1;
        bool flag=1;
        for(int i=1;i<=tot;++i){
            if(a0==1&&a1==1&&b0==1&&b1==1) break;
            int ta0=0,tb0=0,ta1=0,tb1=0;
            int la=0,lb=0,l=0;
            int ra=INF,rb=INF,r=INF;
            while(a0%p[i]==0){
                a0/=p[i];
                ta0++;
            }while(b0%p[i]==0){
                b0/=p[i];
                tb0++;
            }
            while(a1%p[i]==0){
                a1/=p[i];
                ta1++;
            }
            while(b1%p[i]==0){
                b1/=p[i];
                tb1++;
            }
            if(ta0<ta1||tb0>tb1){
                flag=0;
                break;
            }
            la=ta1,rb=tb1;
            if(ta0>ta1) ra=ta1;
            if(tb0<tb1) lb=tb1;
            l=std::max(la,lb);
            r=std::min(ra,rb);
            if(r<l){
                flag=0;
                break;
            }
            ans*=(r-l+1);
        }
        if(!(a0==1&&a1==1&&b0==1&&b1==1)){
            if(a1>a0||b1<b0) flag=0;
            if(a1==a0&&a1!=1) ans<<=1;
            if(b1==b0&&b1!=1) ans<<=1;
        }
        if(!flag) ans=0;
        printf("%d\n",ans);
    }
    return 0;
}

CH3201 Hankson的趣味題