清华机试-约数的个数

题目描述

输入n个整数,依次输出每个数的约数的个数

输入描述:

输入的第一行为N,即数组的个数(N<=1000)
接下来的1行包括N个整数,其中每个数的范围为(1<=Num<=1000000000)
当N=0时输入结束。

输出描述:

可能有多组输入数据,对于每组输入数据,
输出N行,其中每一行对应上面的一个数的约数的个数。
示例1

输入

5
1 3 4 6 12

输出

1
2
3
4
6

解题思路:

确定一个数约数的个数,最简单的方法就是暴力求解,遍历1到该数字,时间复杂度为O(n)。考虑到题中数字的范围为10亿,显然会超时。

联系数学知识,考虑对数字分解质因数,若n = a1b1a2b2a3b3a4b4...ambm(n != 1,其中a1,a2...am均为质数),则约数的个数为∏(bi+1) (i = 1,,2,3...m)。

接下来考虑如何分解质因数。显然暴力的方法也是不行的。一个可行的方法是找出某个范围内的质数,逐个分析,看能否整除n。若不能,尝试下一个质数,若能,记录该质数的bm。

范围的上界应当不小于10亿的平方根。若存在一个大于10亿平方根的数可以整除n,则这个数必然等于n除以小于该数的所有质数的结果,且该数的指数只能为1,否则其平方大于10亿。也就是说,若a大于n的平方根,则其指数只能为1。且最多存在一个这样的a。

接下来考虑如何找到该范围内的所有素数。这里有几种方法,确定一个数是否为素数,暴力的话复杂度是O(n),稍微优化之后是O(sqrt(n))。确定该范围内的所有素数,则时间复杂度为O(n * sqrt(n)),时间复杂度高。

考虑到是找一个范围内的所有素数,且素数的性质(不能被除1和它本身之外的其他数整除),那么当确定一个数为素数时,其倍数都不是素数。由此,可以遍历该范围,每次找到一个素数时,标记其k次方的数为非素数。此算法时间复杂度为O(n * loglogn)。时间复杂度证明参考:https://blog.csdn.net/zzxian/article/details/8263091

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
 
bool flag[40001] = {0};
vector<int> zhi;
 
void shai()
{
    for(int i = 2;i <= 40000;i++)
    {
        if(!flag[i])
        {
            zhi.push_back(i);
            for(long long j = i * i;j <= 40000;j *= i)
            {
//                cout << j << endl;
                flag[j] = 1;
            }
        }
    }
}
 
int yue(int num)
{
    vector<int> v;
    int ans = 1;
    int cnt = 0;
    int zhi_size = (int)zhi.size();
    for(int i = 0;i < zhi_size;)
    {
        int temp = zhi[i];
        if(num < temp) break;
        if(num % temp == 0)
        {
            cnt++;
            num /= temp;
        }
        else
        {
            v.push_back(cnt + 1);
            cnt = 0;
            i++;
        }
    }
    if(cnt != 0) v.push_back(cnt + 1);
    if(num != 1) v.push_back(2);
    int size = v.size();
    for(int i = 0;i < size;i++)
    {
        ans *= v[i];
    }
    return ans;
}
 
int main()
{
    int n;
    shai();
    while(cin >> n)
    {
        if(n == 0) break;
        else
        {
            for(int i = 0;i < n;i++)
            {
                int num;
                cin >> num;
                cout << yue(num) << endl;
            }
        }
    }
    return 0;
}

  



posted on   Tracy-mac  阅读(392)  评论(0编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示