题目传送门
这是清华的一道考研复试题。
我们先上题目:
题目描述 输入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;
}