题目链接:约数的个数
题目描述
输入n个整数,依次输出每个数的约数的个数
输入描述:
输入的第一行为N,即数组的个数(N<=1000)
接下来的1行包括N个整数,其中每个数的范围为(1<=Num<=1000000000)
当N=0时输入结束。
输出描述:
可能有多组输入数据,对于每组输入数据,
输出N行,其中每一行对应上面的一个数的约数的个数。
示例1
输入
5
1 3 4 6 12
输出
1
2
3
4
6
分析: 此前一直用Pollard Rho因数分解(O(n^1/4))来获取质因数,代码如下:
int Factor(int num) {
int s = 0;
int p = 2;
while(true){
if(num == p){
prime[s++] = p;
break;
}
if(num%p){ //不整除
p ++;
}
else{
prime[s++] = p;
num /= p;
}
}
return s;
}
然后,根据约数个数计算公式:x1^p1*x2^p2…xn^pn ->(p1+1)(p2+1)…(pn+1),代码如下:
void Solve(int num) {
if (num == 1) {
printf("1\n");
return;
}
int s = Factor(num);
int ans = 1;
int tmp = prime[0];
int cnt = 1;
for (int i = 1; i < s; i++) {
if (prime[i] == tmp) {
cnt++;
}
else {
ans *= (cnt+1);
tmp = prime[i];
cnt = 1;
}
}
printf("%d\n",ans*(cnt+1));
}
却意外得了0分,究其原因,是因为Pollard Rho因数分解所谓时间效率只是平均效率,如果出现类似999999937的素数,便会Time Limited。
正确的解法是,利用num = a*b,每遇到一个可以整除的数,ans即加2,扫描次数不超过sqrt(num)次
#include <cstdio>
#include <iostream>
using namespace std;
void Solve(int num) {
int ans = 0;
int i;
for (i = 1; i*i < num; i++) {
if (num%i == 0) ans += 2; //num = a*b
}
if (i*i == num) ans += 1;
printf("%d\n",ans);
}
int main() {
int n,num;
while (~scanf("%d", &n)) {
for (int i = 0; i < n; i++) {
scanf("%d", &num);
Solve(num);
}
}
return 0;
}