Description
Given x and y (2 <= x <= 100,000, 2 <= y <= 1,000,000), you are to count the number of p and q such that:
1) p and q are positive integers;
2) GCD(p, q) = x;
3) LCM(p, q) = y.
<b< body="">
Input
x and y, one line for each test.
<b< body="">
Output
Number of pairs of p and q.
<b< body="">
Sample Input
3 60
<b< body="">
Sample Output
4
题目大意:就是找出p*q=x*y,pq的对数。
用一个公式很好:(a/gcd )* ( b/gcd)= lcm/gcd
这样子把lcm的数量级降下来了。而且
因为左边2块互质,这样子递归求解最大公约数时的层次走少了好几步。
program:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int x,y;
int lg;
int gcd(int a,int b)
{
if(a%b==0)return b;
return gcd(b,a%b);
}
void sswap(int & a,int & b)
{
int tmp=a;
a=b;
b=tmp;
}
int main()
{
while(scanf("%d%d",&x,&y)!=EOF)
{
//最小公倍数一定能整除最大公约数!
if(y%x!=0)
{
printf("0\n");
continue;
}
lg=y/x; //(a/gcd )* ( b/gcd)= lcm/gcd
int a,b;
int cnt=0;
for(int i=1;i<=lg;i++)
{
a=i;
if(lg%a==0)
{
b=lg/a; //把问题化为质数问题实在很棒
if(a%2==0&&b%2==0)
continue;
if(a<b)
sswap(a,b);
if(gcd(a,b)==1)
cnt++;
}
}
printf("%d\n",cnt);
}
//system("pause");
return 0;}
总结:其实一个思想很重要:把求解的数转化成和质数有关来求解,因为质数相对合数少很多,所以这样处理问题范围减小很多!
另为什么验证素数的时候只需验证到该数的开方根呢?因为如果n可以被一个数整除,那么就必然有一个因子小于开方根,必然有一个因子大于开方根
因为i=a×b,a与b不能同时大于sqrt(i),为什么呢?如果a>sqrt(i),b>sqrt(i),于是a×b>sqrt(i)*sqrt(i)=i,因此就都不能整除i了!