zoukankan      html  css  js  c++  java
  • 刷题2:约数的个数

    https://www.nowcoder.com/practice/04c8a5ea209d41798d23b59f053fa4d6

    题目

    题目描述
    输入n个整数,依次输出每个数的约数的个数
    输入描述:
    输入的第一行为N,即数组的个数(N<=1000)
    接下来的1行包括N个整数,其中每个数的范围为(1<=Num<=1000000000)
    当N=0时输入结束。
    输出描述:
    可能有多组输入数据,对于每组输入数据,
    输出N行,其中每一行对应上面的一个数的约数的个数。
    示例1
    输入
    复制
    5
    1 3 4 6 12
    输出
    复制
    1
    2
    3
    4
    6
    

    这道题属于那种不再算法思路上设置障碍,但是对时间要求高,逼着你优化算法的。
    我一开始想到的不是这,就是简单的每个数循环,然后cout<<count<<endl;但是超时了。后来又想着用动态规划的思想,设置了一个全局变量int saveResult[1000000001](为什么用全局变量,因为C++中全局变量和静态变量是会自动初始化为0的,但是这其实优点掩耳盗铃的感觉,因为让程序去初始化也是O(n)的,和自己用for循环初始化其实差别不大),但是显示栈溢出。仔细一算可不是嘛,一个int占4个字节,那1000000000*4/1024/1024=3814MB,必然超了。
    好,那我就建了一个map,只有计算出来的才保存进去,这下这里不会影响性能了吧?没想到还是超
    此时就应该能想出来,问题是出在计算的那个环节。试了一下只计算一般,也就是for(int j=1;j<=temp/2;j++),还是超
    这个是我写的解法

    #include<bits/stdc++.h>
    using namespace std;
    map<int,int>saveResult;
    int main(){
        int n;
        int temp;
        int count=0;
        while(cin>>n){
            for(int i=0;i<n;i++){
                cin>>temp;
                if(saveResult.count(temp)==1)
                    cout<<saveResult.find(temp)->second<<endl;
                else{
                    if(temp==1)
                        cout<<1<<endl;
                    else{
                    for(int j=1;j<=temp/2;j++){
                        if(temp%j==0)
                            count+=2;
                    }
                    cout<<count<<endl;
                    saveResult[temp]=count;
                    count=0;
                    }
                }
            }
        }
        return 0;
    }
    

    最后看别人写的,其实就是在我最原始的算法中改动了一个点,for循环从j<=temp/2变成了j*j<temp

    //i*i<num的形式,数值稳定性更好
    #include<iostream>
    using namespace std;
    int numOfDivisor(int num)
    {
        int ans = 0;
        int i;
        for (i = 1; i*i<num; i++)
        {
            if (num%i == 0)
                ans += 2;
        }
        if (i*i == num) ans++;
        return ans;
    }
    int main()
    {
        int n, num;
        while (cin >> n)
        {
            for (int i = 0; i<n; i++)
            {
                cin >> num;
                cout << numOfDivisor(num) << endl;
            }
        }
        return 0;
    }
    

    这个改动我是服气的。因为我们要求的其实就是a*b=const,然后找max{min{a,b}},而最大的就是a*a=const,也就是a=sqrt(const)了。所以遍历到这里就可以了。另外,上面的算法还考虑到了,如果是j*j<temp,那说明有两个不一样的根,所以加二;而如果是j*j=const,就只有一个根了,所以加1.
    它也没用动态规划的那一套,如果时间要求更严格些是可以用的。


    最后,补充一些相关知识吧:

    1. 基本类型所占字节数
      32位编译器:

    char      short      int      long      float      double      指针

    1            2           4         4            4              8            4

    64位编译器:

    char      short      int      long      float      double      指针

    1            2           4         8            4              8            8
    就只有long和指针有区别
    2. STL类型如何随机访问
    * vector就很方便,下标或者at(int index)就可以
    * list可以用count()来判断元素是否存在,find()来找到位置,注意find()返回的是个迭代器,要在前面使用*来取迭代器指向的元素
    * map可以使用find()返回迭代器,然后
    使用iter->second来访问迭代器指向的元素**

  • 相关阅读:
    Mali 水题
    树状数组求区间最值
    POJ1125 Stockbroker Grapevine 最短路
    jquery radio取值,checkbox取值,select取值 及选中(引用)
    过滤注入代码的存储过程
    怎么进行项目管理
    现在已经不喜欢注释而喜欢直接看代码了
    风潮唱片总目录及下载地址2009年2月9日更新
    什么时候用存储过程
    sql server 外键 更新(删除)规则
  • 原文地址:https://www.cnblogs.com/jiading/p/12341159.html
Copyright © 2011-2022 走看看