2
41 1 96 288
95 1 37 1776
6
2
可以用数学公式推导一下:
lcm(x,b0)=x*b0/gcd(x,b0)=b1
b1=x*b0/gcd(x,b0)
gcd(x,b0)=x*b0/b1
gcd(x,b0)*b1/(x*b0)=1
gcd(x,b0)/(x*b0)*b1=1
gcd(x/x*b0,b0/x*b0)*b1=1
gcd(1/b0,1/x)*b1=1
gcd(b1/b0,b1/x)=1
这应该是史上最详尽的数学推导了。。。
可能在这里看着有点乱,看不懂的话抄到纸上一目了然,,不过还需要基础的最大公约数和最小公倍数的公式,不知道请自行百度。。。
然后我们还可以把gcd(x,a0)=a1化简为gcd(x/a1,a0/a1)=1
这样我们就可以根据这两个公式来判断。
还有一个小优化:成立的条件是:a0%a1=0 b1%b0=0 b1%x=0 x%a1=0 加了这四个判断条件程序跑得飞快。
代码很短。
【代码】
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,a0,a1,b0,b1,x,ans; int gcd(int a,int b){ if (b==0) return a; else return gcd(b,a%b); } int main(){ scanf("%d",&n); while (n>0){ ans=0; scanf("%d%d%d%d",&a0,&a1,&b0,&b1); if (a0%a1||b1%b0) {printf("0\n"); n--; continue;} for (int i=1;i*i<=b1;++i) if (b1%i==0){ x=i; if (x%a1==0) if (gcd(a0/a1,x/a1)==1&&gcd(b1/b0,b1/x)==1) ans++; x=b1/i; if (x!=i&&x%a1==0) if (gcd(a0/a1,x/a1)==1&&gcd(b1/b0,b1/x)==1) ans++; } printf("%d\n",ans); n--; } }