题意:给你两个数,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)*p2^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 longusing 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;}