hdu 1299 好题

好题啊,赞一个~先是没思路,问了别人,才知道只要令x = n + a, y = n + b因为x 和y 一定大于n(这个很好想),就能将问题转化为求n*n = a * b以a和b为变量的方程的解的个数,而这个方程解的个数正好可以用n*n这个数的所有因子个数(设为num)来表示,即(num + 1) / 2。想到这还卡了一会儿,因为这个也不好求,n*n就成了long long 范围了。花了好久才想到,只要能够求出n的各个素因子的个数,n*n的素因子个数只是翻倍而已。从而,就可以用打素数表的方法(这里也有一个小技巧,只要打到根号n的素数表即可,因为n*n的素因子中,如果有大于根号n的,那么一定只有一个这样的素数,它的个数是2)。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;

const int MAXI = 4300;
const int MAXV = 40000;
int prime[MAXI], I;
int facnum[MAXI];

void init() {
I = 0;
prime[I++] = 2;
int sqr, j;
for (int i = 3; i < MAXV; i++) {
sqr = (int) sqrt(i);
for (j = 2; j <= sqr; j++) {
if (i % j == 0) {
break;
}
}
if (j > sqr) {
prime[I++] = i;
}
}
}

int main() {
// freopen("data.in", "r", stdin);
int T, n;
long long ans;
init();
scanf("%d", &T);
for (int t = 1; t <= T; t++) {
scanf("%d", &n);
memset(facnum, 0, sizeof(facnum));
for (int i = 0; i < I; i++) {
if (n <= 1) {
break;
}
while (n % prime[i] == 0) {
n /= prime[i];
facnum[i]++;
}
}
ans = 1;
for (int i = 0; i < I; i++) {
if (facnum[i] > 0) {
ans *= (facnum[i] * 2 + 1);
}
}
if (n > 1) {
ans *= 3;
}
printf("Scenario #%d:\n%lld\n\n", t, ans / 2 + 1);
}
return 0;
}




原文地址:https://www.cnblogs.com/moonbay/p/2214426.html