输入n个整数,依次输出每个数的约数的个数。
输入格式
第一行包含整数n。
第二行包含n个整数ai。
输出格式
共n行,按顺序每行输出一个给定整数的约数的个数。
数据范围
1≤n≤1000,
1≤ai≤10^9
输入样例:
5
1 3 4 6 12
输出样例:
1
2
3
4
6
直接暴力枚举会出现TLB超时,由于这里 a 的范围是 1e9,需要去缩短枚举的范围。
将判断条件由i<a缩短到ii<a,时间复杂度由O(n^2)缩短为O(根号n),那么为什么这样做呢,可以观察到,约数是成对出现的。比如24,你找到个约数3,那么一定有个约数8,因为24/3=8。然后,这对约数必须一个在根号n之前,一个在根号n之后。因为都在根号n之前的话,乘积一定小于n(根号n乘根号n=n),同样,都在根号n之后的话,乘积一定大于n。所以,如果你在根号n之前都找不到约数的话,那么根号n之后就不会有了。
进入 for(int i = 1;i i<= n;i++) 循环后,如果 n% i == 0 ,那么说明此时的 i 值是 n 的一个约数,当i<n时,统计约数个数的计数器count此时应该+2,以12为例,12/2=6,此时2和6都是12的约数。
注意注意注意:若ii==n时,如22=4,2是一个因数,count应该+1,不应该加2(因为2与2是同一个约数)
C++代码
(优化版的枚举,不会出现TLB)
include [HTML_REMOVED]
using namespace std;
int num(int s) {
int count = 0;
for (int i = 1;i *i<= s;i) {
if (s % i == 0) {
if (s == i * i)
count;
else
count += 2;
}
}
return count;
}
int main() {
int n;
int a[1000];
cin >> n;
int m = n;
for (int j = 0;j < m;j++) {
cin >> a[j];
cout << num(a[j]) << endl;
}
return 0;
}