题目描述
输入n个整数,依次输出每个数的约数的个数。
输入
输入的第一行为N,即数组的个数(N<=1000)
接下来的1行包括N个整数,其中每个数的范围为(1<=Num<=1000000000)
当N=0时输入结束。
输出
可能有多组输入数据,对于每组输入数据,
输出N行,其中每一行对应上面的一个数的约数的个数。
样例输入
6
1 4 6 8 10 12
0
样例输出
1
3
4
4
4
6
思路一:直接计算约数个数,到sqrt(num)时为止。
#include <cstdio>
#include <cmath>
int cnt(long long num) {
int sum = 0;
int sqr = sqrt(num);
for (int i = 1; i <= sqr; i++) {
if (num % i == 0) sum += 2; //可以被i整除,表明有两个对应因子
}
if (num == sqr * sqr) sum--; //考虑num=sqr*sqr时重复计算了一次
return sum;
}
int main() {
int n;
long long num;
while (scanf("%d", &n), n != 0) {
while (n--) {
scanf("%lld", &num);
printf("%d\n", cnt(num));
}
}
return 0;
}
思路二:使用如下的结论。

#include <cstdio>
#include <cmath>
const int maxn = 100010; //表长
int prime[maxn], pNum = 0; // prime数组存放所有素数,pNum为素数个数
bool p[maxn] = {false}; // 如果i为素数,则p[i]为false,否则p[i]为true
struct factor {
int x, cnt; // x为质因子,cnt为其个数
} fac[20];
void Find_Prime() {
for (int i = 2; i < maxn; i++) {
if (p[i] == false) { //如果i是素数
prime[pNum++] = i;
//从2*i开始
for (int j = 2 * i; j < maxn; j += i) {
//筛去所有i的倍数
p[j] = true;
}
}
}
}
int cnt(long long num) { //埃式筛法求素数表
int n = 0, sum = 1; // n为不同质因子个数,sum为所求约数个数
int sqr = (int)sqrt(1.0 * num); // n的根号
//枚举根号n以内的质因子
for (int i = 0; i < pNum && prime[i] <= sqr; i++) {
if (num % prime[i] == 0) { //如果prime[i]是n的质因子
fac[n].x = prime[i]; //记录该质因子
fac[n].cnt = 0;
//计算质因子prime[i]的个数
while (num % prime[i] == 0) {
fac[n].cnt++;
num /= prime[i];
}
n++; //不同质因子个数加1
}
if (num == 1) break;
}
if (num != 1) { //如果n不为1,说明n有且仅有一个大于sqrt(n)的质因子
fac[n].x = num;
fac[n++].cnt = 1;
}
for (int i = 0; i < n; i++) {
sum *= fac[i].cnt + 1; //按照上述公式计算
}
return sum;
}
int main() {
Find_Prime();
int n;
long long num;
while (scanf("%d", &n), n != 0) {
while (n--) {
scanf("%lld", &num);
printf("%d\n", cnt(num));
}
}
return 0;
}
1486

被折叠的 条评论
为什么被折叠?



