zoukankan      html  css  js  c++  java
  • 清华机试-约数的个数

    题目描述

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

      



  • 相关阅读:
    javascript定义函数后立即执行(IIFE)
    工作流选型专项,Camunda or flowable or?
    Excel中的xlsm宏密码怎么破解
    《生命是什么》总结
    《麦肯锡教我的思考武器》总结
    《作为意志和表象的世界》总结
    Go语言如何将json时间格式化为dateime格式
    《少有人走的路》总结
    《时间简史》总结
    架构的常规分类及复用重点
  • 原文地址:https://www.cnblogs.com/tracy520/p/8728745.html
Copyright © 2011-2022 走看看