题意:给你两个数,G和L ,它们是一组数的GCD(最大公约数)和LCM(最小公倍数),求出满足条件的组合数,每个组合有三个数,排序不同,也算不同组合。
L : p1^t1 * p2^t2 ... * pi^ti
G: q1^s1 * q2^s2... * qi^si
(pi和qii都是素数ii)
G(最大公约数)里出现的所有数都要在L(最小公倍数)里出现,或者说L mod G=0,有人要问为什么了?其实仔细想想就清楚了,如果a,b,c的最小公倍数肯定可以被a,b,c任意一个整除,而他们的最大公约数肯定可以整除a,b,c任意一个,所里理所当然,L%G=0,如果L%G!=0说明没有符合条件的数,直接输出0就好了。
有一组数(a,b,c)
a = p1^i1 * p2^i2 * p3^i3 * ……
b = p1^j1 * p2^j2 * p3^j3 * ……
c = p1^k1 * p2^k2 * p3^k3 * ……
(pi是素数)
他们的G=p1^min(i1,j1,k1)*p2^min(i2,ji2,k2)*...
他们的L=p1^max(i1,j1,k1)*p1^max(i2,j2,k2)*....
令k=L/G;
所以 k=p1^x1*p2^x2...
现在我们可以使a,b,c他们三个都是G,现在要让他们的最小公倍数是L,对于P1来说a,b,c至少一个数数要乘以p1^x1才能保证L中的p1的指数,又要让他们的最大公约数等于G,至少有一个p1的指数不变(即乘以p1^0),另外一个的乘以p1^t1(0<=t1<=x1),就能保证L中P1的指数,以此推类每个Pi都要满足这个条件,所以每个Pi组合数就有C(x1+1,1)*A(3,3)i,又考虑到
ti=0,和ti=xi ,这两种情况排列数中3个所以对于每个pi应该是(3+3)+C(xi+1-2,1)*A(3,3)=6+(x1-1)*6=6*x1,最后各个pi的情况相乘就可以了。
#include<stdio.h>
#include<cstring>
#include<iostream>
#define ll long long
using namespace std;
ll flag[100000];
ll prime[100000];
ll fa[100000];
ll cnt=0;
void factor(int nn)//得到素数幂指数
{
int cas=0;
for(int i=0;i<cnt&&prime[i]*prime[i]<=nn;i++)//关于为什么prime[i]*prime[i]<=nn,如果还有更大的素数,prime[i]*prime[i]>nn(prinme[i]*更大的素数)
{
while(nn%prime[i]==0)
{
fa[cas]++;
nn/=prime[i];
}
if(fa[cas])
cas++;
}
if(nn>1)
fa[cas]=1;
}
int main ()
{
memset(flag,1,sizeof(flag));
for(int i=2;i<100000;i++)//素数筛,原理是把每个素数的倍数筛出来,从小到大,不过还有更快的筛法,大家可以去网上搜一搜
{
if(flag)
{
for (int j=i+i;j<100000;j+=i)
{
flag[j]=0;
}
}
}
memset(prime,0,sizeof(prime));
for(int i=2;i<100000;i++)
{
if(flag)
{
prime[cnt++]=i;
}
}
ll t,g,l;
scanf("%lld",&t);
while (t--)
{
memset(fa,0,sizeof(fa));
scanf("%lld %lld",&g,&l);
ll k=l/g;
if(l%g!=0)
{
printf("0\n");
continue;
}
factor(k);
ll sum=1;
for(int i=0;;i++)
{
if(!fa[i])
{
break;
}
sum*=fa[i];
sum*=6;
}
printf("%d\n",sum);
}
return 0;
}