Hankson 的趣味题
这是一道关于求最小公倍数、最大公约数逆运算的一道题。
做这道题首先要会求最大公约数和最小公倍数 ,对吧……
题目要求解个数,我们来看一看条件:
50分做法:
我们从条件中很容易看出x的范围——大于等于a1并且小于等于b1,所以我们暴力枚举a1到b1,然后对于每个可能的答案按照条件进行判断
代码:
#include<bits/stdc++.h> #define R register int using namespace std; typedef long long ll; ll n,a0,a1,b0,b1,ans; inline ll gcd(ll x,ll y){ ll z; while(y){ z=x%y; x=y; y=z; } return x; } int main(){ ios::sync_with_stdio(0); cin>>n; for(R t=1;t<=n;++t){ cin>>a0>>a1>>b0>>b1; ans=0; for(R i=a1;i<=b1;++i) if(gcd(i,a0)==a1 && i*b0/gcd(i,b0)==b1) ++ans; printf("%lld\n",ans); } return 0; }
AC做法:
在讲AC做法之前,我先说两个需要知道的关于最大公约数和最小公倍数的结论。
最大公约数:如果gcd(x,y)=z,那么gcd(x/z,y/z)=1。这个大家应该都知道,就不细讲了。
最小公倍数:
①如果lcm(x,y)=z,那么gcd(z/y,z/x)=1。这个我们来证明一下:我们设lcm(x,y)=z,那么lcm(x,y)=x*y/gcd(x,y)=z,所以gcd(x,y)=x*y/z。由最大公约数结论可得,gcd(z/y,z/x)=1。
②如果y是x的公倍数,则x是y的因数,也就是y % x == 0。
由上面几条结论可得,x一定是b1的因数,而且x % a1 == 0,gcd(x/a1 ,a0/a1) == 1,gcd(b1/b0 ,b1/x) == 1。
那么我们就可以枚举b1的因数,然后判断了。
代码:
#include<bits/stdc++.h> #define R register int using namespace std; int n,a0,a1,b0,b1,ans; inline int gcd(int x,int y){ if(!x) return y; if(!y) return x; R i,j; for(i = 0; !(x & 1); ++i) x >>= 1; for(j = 0; !(y & 1); ++j) y >>= 1; if(j < i) i = j; for(;;){ if(x < y) x ^= y,y ^= x,x ^= y; if(0 == (x %= y)) return y << i; while(!(x & 1)) x>>=1; } } int main(){ ios::sync_with_stdio(0); cin>>n; for(R t=1;t<=n;++t){ cin>>a0>>a1>>b0>>b1; int p=a0/a1,q=b1/b0; ans=0; for(R x=1;x*x<=b1;++x) if(b1%x==0){ if(x % a1 == 0 && gcd(x/a1,p)==1 && gcd(b1/x,q)==1) ++ans; int y=b1/x; if(x==y) continue; if(y % a1 ==0 && gcd(y/a1,p)==1 && gcd(b1/y,q)==1) ++ans; } printf("%d\n",ans); } return 0; }