zoukankan      html  css  js  c++  java
  • 九度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
    ",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 }
  • 相关阅读:
    高精度计算
    高精度除以低精度
    P1258 小车问题
    POJ 2352 stars (树状数组入门经典!!!)
    HDU 3635 Dragon Balls(超级经典的带权并查集!!!新手入门)
    HDU 3938 Portal (离线并查集,此题思路很强!!!,得到所谓的距离很巧妙)
    POJ 1703 Find them, Catch them(确定元素归属集合的并查集)
    HDU Virtual Friends(超级经典的带权并查集)
    HDU 3047 Zjnu Stadium(带权并查集,难想到)
    HDU 3038 How Many Answers Are Wrong(带权并查集,真的很难想到是个并查集!!!)
  • 原文地址:https://www.cnblogs.com/jasonJie/p/5682403.html
Copyright © 2011-2022 走看看