CH3201 Hankson的趣味題
題意
3201 Hankson的趣味題 0x30「數學知識」例題
描述
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的趣味題