- 题目描述:
-
输入n个整数,依次输出每个数的约数的个数
- 输入:
-
输入的第一行为N,即数组的个数(N<=1000)
接下来的1行包括N个整数,其中每个数的范围为(1<=Num<=1000000000)
当N=0时输入结束。
- 输出:
-
可能有多组输入数据,对于每组输入数据,
输出N行,其中每一行对应上面的一个数的约数的个数。
- 样例输入:
-
5 1 3 4 6 12
- 样例输出:
-
1 2 3 4 6
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 7 long long int cal(long long int num) { 8 if(num == 1) { 9 return 1; 10 } 11 long long ans = 2; 12 long long int middle = sqrt(num); 13 if(middle * middle == num) { 14 ans++; 15 } 16 else { 17 middle++; 18 } 19 for(long long int i = 2; i < middle; i++) { 20 if(num % i == 0) { 21 ans = ans + 2; 22 } 23 } 24 return ans; 25 } 26 27 int main(int argc, char const *argv[]) 28 { 29 int N; 30 long long int num; 31 scanf("%d",&N); 32 while(N != 0) { 33 for(int i = 0; i < N; i++) { 34 scanf("%lld",&num); 35 long long res = cal(num); 36 printf("%lld ",res); 37 } 38 scanf("%d",&N); 39 } 40 return 0; 41 }
题目不难,但要注意特殊情况以及取值范围,int的最大值大概是2的9次方
----9-17更新
题目其实并没有超过int的范围
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 7 int cal(long long int num) { 8 if(num == 1) { 9 return 1; 10 } 11 int ans = 0; 12 int middle = sqrt(num); 13 for(int i = 1; i <= middle; i++) { 14 if(num % i == 0) { 15 ans = ans + 2; 16 } 17 } 18 if(middle*middle == num) { 19 ans--; 20 } 21 return ans; 22 } 23 24 int main(int argc, char const *argv[]) 25 { 26 int N; 27 int num; 28 scanf("%d",&N); 29 while(N != 0) { 30 for(int i = 0; i < N; i++) { 31 scanf("%d",&num); 32 int res = cal(num); 33 printf("%d ",res); 34 } 35 scanf("%d",&N); 36 } 37 return 0; 38 }
还有另一种更快的方法是
对于一个数n
n可以写成几个素数的ai次方的乘积
则n的约数个数为(a1+1)*(a2+1)*(a3+1)*...
实验了一下这个方法,开始还想着去求素数,再一个个的比较,代码如下
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 #define Prime_Cnt 1002 7 8 int prime[1002]; 9 int fp[1002]; 10 int cnt[1002]; 11 12 int getPrime() { 13 memset(fp, 0, sizeof(fp)); 14 int p = 0; 15 for(int i = 2; i < Prime_Cnt; i++) { 16 if(fp[i] == 0) { 17 prime[p++] = i; 18 for(int j = 2*i; j < Prime_Cnt; j+=i) { 19 fp[j] = 1; 20 } 21 } 22 } 23 return p; 24 } 25 26 int cal(int n, int p) { 27 if(n == 1) { 28 return 1; 29 } 30 memset(cnt, 0, sizeof(cnt)); 31 int i = 0; 32 int ans = 1; 33 while(n != 1) { 34 int tmp = 0; 35 while(n%prime[i] != 0) { 36 i++; 37 } 38 while(n%prime[i] == 0) { 39 n = n/prime[i]; 40 tmp++; 41 } 42 ans = ans *(tmp+1); 43 cnt[i] = tmp; 44 } 45 return ans; 46 } 47 48 49 int main(int argc, char const *argv[]) 50 { 51 int N; 52 int num; 53 int p = getPrime(); 54 while(scanf("%d",&N) != EOF && N != 0) { 55 for(int i = 0; i < N; i++) { 56 scanf("%d",&num); 57 int ans = cal(num, p); 58 printf("%d ", ans); 59 } 60 61 } 62 return 0; 63 }
但runtime error
后来发现可以有不求素数的办法
代码如下
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 6 int cal(int n) { 7 if(n == 1) { 8 return 1; 9 } 10 int i = 2; 11 int ans = 1; 12 while(n != 1) { 13 int tmp = 0; 14 while(n%i != 0) { 15 i++; 16 } 17 while(n%i == 0) { 18 n = n/i; 19 tmp++; 20 } 21 ans = ans *(tmp+1); 22 } 23 return ans; 24 } 25 26 27 int main(int argc, char const *argv[]) 28 { 29 int N; 30 int num; 31 while(scanf("%d",&N) != EOF && N != 0) { 32 for(int i = 0; i < N; i++) { 33 scanf("%d",&num); 34 int ans = cal(num); 35 printf("%d ", ans); 36 } 37 38 } 39 return 0; 40 }
但时间反而更长了,不知道为啥
最后看了看大神的代码,是这样写的:
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 6 7 int main(int argc, char const *argv[]) 8 { 9 int N; 10 int n; 11 while(scanf("%d",&N) != EOF && N != 0) { 12 while(N--) { 13 scanf("%d",&n); 14 int i = 2; 15 int ans = 1; 16 17 for(; i*i <= n; i++) { 18 if(n % i == 0) { 19 int tmp = 1; 20 while(n%i == 0) { 21 tmp++; 22 n=n/i; 23 } 24 ans = ans*tmp; 25 } 26 } 27 if(n > 1) ans = ans*2; 28 printf("%d ", ans); 29 } 30 31 } 32 return 0; 33 }
第27行的意思是如果退出时还没有除尽的话,那么也就剩下最后一个素数了,所以ans = ans * 2
自己写了一个代码如下
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 7 8 int main(int argc, char const *argv[]) 9 { 10 int N; 11 int n; 12 while(scanf("%d",&N) != EOF && N != 0) { 13 while(N--) { 14 scanf("%d",&n); 15 int i = 2; 16 int ans = 1; 17 int q = sqrt(n); 18 while(n != 1) { 19 int tmp = 1; 20 while(n % i == 0) { 21 n = n/i; 22 tmp++; 23 } 24 25 ans = ans * tmp; 26 if(i == q+1) { 27 break; 28 } 29 i++; 30 } 31 if(n != 1) { 32 ans = ans * 2; 33 } 34 printf("%d ", ans); 35 } 36 37 } 38 return 0; 39 }