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

Hankson 的趣味題

div 這樣的 最小公倍數 求解 wap ios == ans 個數

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 的趣味題