Hankson 的趣味题
Posted wzq--boke
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 ",ans); } return 0; }
以上是关于Hankson 的趣味题的主要内容,如果未能解决你的问题,请参考以下文章