思路:因为1/x + 1/y = 1/n,则x+y / xy = 1/n,令x = n+a, y = n+b(x,y必定大于n),则等式可以化成a*b = n^2;因为a,b都是整数,所以a,b必定是n^2的约数,找出n^2的所有约数,即可找出所有满足题意的解。由于要满足x <= y所以只需找出a <= b的解的个数即可,设约数个数为num,则答案为(num+1)/2。那么如何找出n^2的约数个数呢?因为n <= 10^9,则n^2是一个很大的数,在时间和空间上都不允许直接操作,考虑到任何整数n都可以表示为
n = p1^e1*p2^e2*..pn^en,其中p1,p2..,pn都为素数,并且n的约数个数为 (1+e1)*(1+e2)*...(1+en);所以n^2 = (p1^e1*p2^e2...pn^en)^2 = p1^2e1*p2^2e2...*pn^2en,故其约数个数为(1+2e1)*(1+2e2)*...(1+2en);所以只需求出n的约数个数即可,每次求出ek(k=1,2,3,4..)的时候,将结果乘上2即可。同时,要找10^9以内的素数,范围比较大,其实只需求出sqrt(10^9)以内的素数即可,因为大于sqrt(10^9)的素数必定是以自己单独存在的,也就是说,若该素数为pk,则ek必定等于1.(pk^2>10^9,已经比n大了)。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define MAX 40005
int prime[MAX];
int vis[MAX];
int idx;
void findPrime()
{
int i,j;
memset(vis,0,sizeof(vis));
idx=0;
for(i=2;i<=200;i++)
{
if(!vis[i])
{
for(j=i*i;j<=40000;j+=i)
{
vis[j]=1;
}
}
}
for(i=2;i<=40005;i++)
{
if(!vis[i])
{
prime[idx++]=i;
}
}
}
int cal(int n)
{
int ret=1;
int i,time;
for(i=0;i<idx&&prime[i]<=n;i++)
{
time=0;
while(n%prime[i]==0)
{
n/=prime[i];
time++;
}
ret*=(1+time*2);
}
if(n>1)
ret*=3;
return ret;
}
int main()
{
int Case;
int ca,n,ans;
findPrime();
scanf("%d",&Case);
for(ca=1;ca<=Case;ca++)
{
scanf("%d",&n);
ans=cal(n);
printf("Scenario #%d:\n",ca);
printf("%d\n\n",(ans+1)/2);
}
return 0;
}