清华机试-约数的个数

题目描述

输入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

代码:

#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 2018-04-06 20:20  Tracy-mac  阅读(388)  评论(0编辑  收藏  举报

导航