问题 D: 约数的个数

题目描述
输入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;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值