时间限制 | 内存限制 |
---|---|
1000 ms |
65536 KB |
# 题目描述
给定 个数 ,求 的正因数个数。
# 输入
第一行一个正整数 代表数据组数,。
对于每组数据,第一行一个正整数 ,代表数字个数,。第二行 个正整数 ,。
# 输出
对于每组数据,输出一行一个正整数,代表 的不同正因数的个数,其中。
# 输入样例
4 | |
2 | |
6 2 | |
1 | |
17 | |
1 | |
1000000000 | |
3 | |
11 45 14 |
# 输出样例
6 | |
2 | |
100 | |
48 |
# 样例解释
对于第一组样例,, 的正因数有 共 个。
对于第二组样例, 的因数有 共 个。
# 题解:线性筛 + 数论
考虑一个数的质因数分解:
其中 均为质数。我们知道,此时 的正因数个数为 。
我们考虑将 都进行质因数分解,再将同质数的质数相加,就得到了 的质因数分解。但是我们注意到,最大的质数还是 这个量级的,有什么办法吗?
不难发现,大于 的质因数在每次分解 时至多只会出现一次,因此我们考虑将 之前的质数用线性筛先筛出来,然后用它们对 进行分解,如果最后 不为 ,则剩下的必定是一个大于 的质数,我们把它记下来即可。具体细节参考代码实现。
时间复杂度为 。
参考代码:
#include <stdio.h> | |
#include <stdbool.h> | |
#include <string.h> | |
typedef long long ll; | |
int primeCnt, bigPrimeCnt, prime[50010], bigPrime[15], bigPrimePower[15], primePower[50010]; | |
bool notPrime[100010]; | |
void GetPrime() | |
{ | |
notPrime[1] = true; | |
for (int i = 2; i <= 100000; ++ i) | |
{ | |
if (!notPrime[i]) | |
prime[ ++ primeCnt] = i; | |
for (int j = 1; j <= primeCnt && 1ll * i * prime[j] <= 100000; ++ j) | |
{ | |
notPrime[i * prime[j]] = true; | |
if (i % prime[j] == 0) | |
break; | |
} | |
} | |
return; | |
} | |
int main() | |
{ | |
// freopen("H.in", "r", stdin); | |
// freopen("H.out", "w", stdout); | |
GetPrime(); | |
int T; | |
scanf("%d", &T); | |
while (T -- ) | |
{ | |
bigPrimeCnt = 0; | |
memset(bigPrime, 0, sizeof(bigPrime)); | |
memset(bigPrimePower, 0, sizeof(bigPrimePower)); | |
memset(primePower, 0, sizeof(primePower)); | |
int n; | |
scanf("%d", &n); | |
for (int i = 1; i <= n; ++ i) | |
{ | |
int a; | |
scanf("%d", &a); | |
for (int j = 1; j <= primeCnt; ++ j) | |
while (a % prime[j] == 0) | |
{ | |
a /= prime[j]; | |
++ primePower[j]; | |
} | |
if (a > 1) | |
{ | |
int ind = 1; | |
while (ind <= bigPrimeCnt && bigPrime[ind] != a) | |
++ ind; | |
if (ind > bigPrimeCnt) | |
bigPrimeCnt = ind; | |
bigPrime[ind] = a; | |
++ bigPrimePower[ind]; | |
} | |
} | |
ll ans = 1; | |
for (int i = 1; i <= primeCnt; ++ i) | |
ans *= (primePower[i] + 1); | |
for (int i = 1; i <= bigPrimeCnt; ++ i) | |
ans *= (bigPrimePower[i] + 1); | |
printf("%lld\n", ans); | |
} | |
return 0; | |
} |