刷题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和指针有区别

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

猜你喜欢

转载自www.cnblogs.com/jiading/p/12341159.html