题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4497
题目大意:
求gcd(x,y,z)=G且lcm(x,y,z)=L的方法数。
题目分析:
起初这道题一点想法都没有。。看了题解才有些想法。
首先如果L不能被G整除的话,这样的组合一定不存在。
当这样的组合存在的时候,所求与 求gcd(x,y,z)=1且lcm(x,y,z)=L/G的方法数是等价的。
那么:令temp=L/G。
对temp进行素数分解:temp=p1^t1 * p2^t2 * ……* pn^tn。
因为temp是这三个数的倍数,因而x,y,z的组成形式为:
x=p1^i1 * p2^i2 *…… * pn^in;
y=p1^j1 * p2^j2 *…… * pn^jn;
z=p1^k1 * p2^k2 * …… * pn^kn;
对于某一个素因子p:
因为要满足x,y,z的最大公约数为1,即三个数没有共同的素因子,所以min(i,j,k)=0。
又因为要满足x,y,z的最小公倍数为temp,即p^t必然要至少存在一个,所以max(i,j,k)=t。
换言之:至少要有一个p^t,以满足lcm的要求;至多有两个包含p,以满足gcd的要求。
因而基本的组合方式为(0,p^t,p^k),k=0-->t。
而因为(1,2,3)和(2,1,3)是不同的方法,所有满足要求的方法中,除了(0,0,t)和(0,t,t)各有3种排列之外,其余都有6种排列。
对于某一个素因子p总的方法数为6*(t-1)+2*3=6*t。
在根据组合排列的知识,素数与素数之间是分步的关系,因而总的方法数为:6*(t1+t2+……+tn)
那么这道题另外一个地方就是素因子分解的部分了,详细请见本博POJ1845(http://www.cnblogs.com/xiaozhuyang/p/POJ1845-Sumdiv.html)中的相关知识。
反过来想,这道题的出发基础是“整数唯一分解定理”,每一个数都能分解成若干个质数相乘的形式。

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 6 int main() 7 { 8 int t; 9 cin>>t; 10 while(t--) 11 { 12 int G,L; 13 int ti[1000]; 14 cin>>G>>L; 15 if(L%G) 16 { 17 cout<<0<<endl; 18 continue; 19 } 20 int temp=L/G; 21 int k=0; 22 for(int i=2;i*i<=temp;)//根号法+奇偶法+递归 23 { 24 if(temp%i==0) 25 { 26 ti[k]=0; 27 while(temp%i==0) 28 { 29 ti[k]++; 30 temp/=i; 31 } 32 k++; 33 } 34 35 if(i==2) 36 i++; 37 else 38 i+=2; 39 } 40 if(temp!=1)//如果temp本身就是个质数 41 ti[k++]=1; 42 43 long long ans=1LL; 44 for(int i=0;i<k;i++) 45 { 46 ans*=(6*ti[i]); 47 } 48 cout<<ans<<endl; 49 } 50 return 0; 51 }