九度oj 题目1087:约数的个数

题目描述:

输入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\n",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\n",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\n", 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\n", 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\n", 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\n", ans);
35         }
36 
37     }
38     return 0;
39 }

 

posted @ 2016-07-18 19:31  Jason杰  阅读(293)  评论(0编辑  收藏  举报