poj2917

题意:给出n,求1/n=1/x+1/y(n,x,y=1,2,3...)的解的个数

分析:n = (x*y)/(x+y)
(x+y)*n = x*y
设x = n+a; y = n+b
带入可以得到
n*n = a*b
题目就转化成了求所有整数对使得a*b = n*n。

即求n*n的约数个数,由于约数都是成对出现的,两数乘积为n^2,为奇数是因为n与n成对出现,而只计算了1次。为避免重复,设约数个数为p,(p + 1)/2即为所求。

然而n*n过大不能直接求约数。我们用求质因子的方法求约数个数,我们只需求n的素因子,每个个数乘2即为n*n的每个素因子个数。

View Code
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

#define N 100005

bool is[N];
int prm[N];
int n;

int getprm(int n)
{
int i, j, k = 0;
int s, e = (int)(sqrt(0.0 + n) + 1);
memset(is, 1, sizeof(is));
prm[k++] = 2;
is[0] = is[1] = 0;
for (i = 4; i < n; i += 2)
is[i] = 0;
for (i = 3; i < e; i += 2)
if (is[i])
{
prm[k++] = i;
for (s = i * 2, j = i * i; j < n; j += s)
is[j] = 0;
}
for (; i < n; i+= 2)
if (is[i])
prm[k++] = i;
return k;
}

int main()
{
//freopen("t.txt", "r", stdin);
int t;
scanf("%d", &t);
n = getprm(100000);
for (int i = 0; i < t; i++)
{
printf("Scenario #%d:\n", i + 1);
int x;
scanf("%d", &x);
int ans = 1;
for (int i = 0; i < n && prm[i] * prm[i] <= x; i++)
{
int cnt = 0;
while (x % prm[i] == 0)
{
x /= prm[i];
cnt++;
}
ans *= cnt * 2 + 1;
}
if (x > 1)
ans *= 3;
printf("%d\n", (ans + 1) / 2);
putchar('\n');
}
return 0;
}
原文地址:https://www.cnblogs.com/rainydays/p/2201969.html