Hankson 的趣味題
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 的個數。請你幫助他編程求解這個問題。
首先把條件轉化成數學式子
a1=gcd(x,a0);
b1=lcm(x,b0);
顯然你會發現gcd比lcm好求,所以我們把第二個式子轉化一下
首先你要知道個定理a*b=gcd(a,b)*lcm(a,b);
所以第二個式子轉化過程
x*b0=lcm(x,b0)*gcd(x,b0);
x*b0=b1*gcd(x,b0);
x=b1/b0*gcd(x,b0);
整理一下
a1=gcd(x,a0);
x=b1/b0*gcd(x,b0);
首先可以很暴力想到枚舉x進行判斷,這樣只能拿50分所以我們要優化一下
因為gcd(x,b0)<=b0 而gcd(x,b0)為b0約數,所以我們枚舉gcd(x,b0),且gcd(x,b0)<=sqrt(b0);
令i=gcd(x,b0) 1<=i<=sqrt(b0);
判斷x=b1/b0*i 和x=b1/b0*(b0/i)是否滿足條件
還要有些特判,具體看代碼
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define ll long long using namespace std; const int maxn=1000000+10101; inline int read(){ int x=0,f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-‘0‘; return x*f; } int n,a0,a1,b0,b1; int gcd(int x,int y){ if(x<y)swap(x,y); if(y==0)return x; return gcd(y,x%y); } int main(){ n=read(); for(int i=1;i<=n;i++){ int ans=0; a0=read();a1=read();b0=read();b1=read(); int kk=sqrt(b0); for(int i=1;i<=kk;i++){ if(b0%i!=0)continue; //註意1 int x1=b1/b0*i; if(gcd(x1,a0)==a1 && gcd(x1,b0)==i)ans++; if(b0/i==i)continue;//註意2 x1=b1/b0*(b0/i); if(gcd(x1,a0)==a1 && gcd(x1,b0)==b0/i)ans++; } printf("%d\n",ans); } return 0; }
Hankson 的趣味題