计算机历年考研复试上机题------约数个数

题目传送门
这是清华的一道考研复试题。

我们先上题目:

题目描述 输入n个整数,依次输出每个数的约数的个数 输入描述: 输入的第一行为N,即数组的个数(N<=1000)
接下来的1行包括N个整数,其中每个数的范围为(1<=Num<=1000000000) 当N=0时输入结束。 输出描述:
示例1
输入

5 1 3 4 6 12
输出

1 2 3 4 6

这道题可以有两种方法
第一种:直接直接遍历1 到 根号n 找到一个因数计数+2【因为根号n * 根号n 的值是等于那么其他成对的因数,必定是一个大于根号n,一个小于根号n】

#include<iostream>
using namespace std;
int main()
{
    int n;
    while (~scanf("%d",&n))
    {
        int num;
        while (n--)
        {
            scanf("%d",&num);
            int ans = 0;
            int i;
            for (i = 1; i*i <    num; i++)
            {
                if(num%i == 0) ans+=2;
            }
            if(i*i==num) ans++;
            printf("%d\n", ans);
        }
    }
    return 0;
}

第二种:利用 约数个数定理【提示一下排列组合可以求得每一个因数】,其中我们必须要理解质因数这个概念,就是说当前得这个因数除了 1 和他本身以外没有其它的因数了。
感谢某位C姓同学的耐心讲解

#include<iostream>  
using namespace std;
int main()
{
    int n;
    while (~scanf("%d",&n))
    {
        int num;
        while (n--)
        {
            scanf("%d",&num);
            int ans = 1;
            /*
            *从最小开始我们一直num除以他的约数这样
            *以后我们遇到约数的倍数的时候他就不再是
            *当前num的约数了。这样就可以求出他的次幂
            */
            for (int i = 2; i*i <=   num; i++)
            {
                int flag = 0;
                while (num%i == 0)
                {
                    flag++;
                    num = num / i;
                }
                /*
                * ans * (en + 1)
                *e1+1 到 en+1 的连乘
                */
                if (flag)
                {
                    ans = ans*(++flag);
                }
            }
            /*
            *由于算法优化的原因我们只算到了 根号n
            *他在大于 根号n 的地方仍然可能有至多一个
            *质因数 所以数量 *2
            */
            if (num > 1)
            {
                ans = ans * 2;
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34333801/article/details/80380226
今日推荐