zoukankan      html  css  js  c++  java
  • HDOJ2138+HDOJ1215 素数查找、素数约数和公式问题[总结:筛选法]


    How many prime numbers

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 6628    Accepted Submission(s): 2160


    Problem Description
      Give you a lot of positive integers, just to find out how many prime numbers there are.
     
    Input
      There are a lot of cases. In each case, there is an integer N representing the number of integers to find. Each integer won’t exceed 32-bit signed integer, and each of them won’t be less than 2.
     
    Output
      For each case, print the number of prime numbers you have found out.
     
    Sample Input
    3 2 3 4
     
    Sample Output
    2
     
    Author
    wangye
     
    Source
     
    Recommend
    威士忌
     
     
     1 #include<iostream>
     2 #include<cmath>
     3 using namespace std;
     4 
     5 bool data[10000000];
     6 #define max 10000000
     7 
     8 bool dep(int num)
     9 {
    10     int i;
    11     for(i=2;i<sqrt(num);i++)
    12     {
    13         if(num%i==0)
    14             return true;
    15     }
    16     return false;
    17 }
    18 
    19 int main()
    20 {
    21     int i,j;
    22     int num;
    23     int count;
    24     int number;
    25     memset(data,0,sizeof(data));
    26     for(i=2;i<=5000000;i++)
    27     {
    28         if(data[i]==0)
    29             for(j=i+i;j<=10000000;j+=i)
    30                 data[j]=1;
    31     }
    32     while(~scanf("%d",&num))
    33     {
    34         count=0;    
    35         for(i=0;i<num;i++)
    36         {
    37             scanf("%d",&number);
    38             if(number>=max)
    39             {
    40                 if(!dep(number))
    41                     count++;
    42             }
    43             else if(!data[number])
    44                 count++;
    45         }            
    46         printf("%d\n",count);
    47     }
    48     return 0;
    49 }

    筛选法核心:

    for(i=2;i<=5000000;i++)
     {
      if(data[i]==0)
       for(j=i+i;j<=10000000;j+=i)
        data[j]=1;
     }


    七夕节

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 17449    Accepted Submission(s): 5198


    Problem Description
    七夕节那天,月老来到数字王国,他在城门上贴了一张告示,并且和数字王国的人们说:"你们想知道你们的另一半是谁吗?那就按照告示上的方法去找吧!"
    人们纷纷来到告示前,都想知道谁才是自己的另一半.告示如下:



    数字N的因子就是所有比N小又能被N整除的所有正整数,如12的因子有1,2,3,4,6.
    你想知道你的另一半吗?
     
    Input
    输入数据的第一行是一个数字T(1<=T<=500000),它表明测试数据的组数.然后是T组测试数据,每组测试数据只有一个数字N(1<=N<=500000).
     
    Output
    对于每组测试数据,请输出一个代表输入数据N的另一半的编号.
     
    Sample Input
    3 2 10 20
     
    Sample Output
    1 8 22
     
    Author
    Ignatius.L
     
    Source
     
     
     
    code:
      1 #include<iostream>
      2 #include<cmath>
      3 using namespace std;
      4 
      5 int data[500000];
      6 
      7 int main()
      8 {
      9     int n;
     10     int num;
     11     int result;
     12     int temp;
     13     int i,j;
     14     int tip=0;
     15     int p,q,r;
     16     memset(data,0,sizeof(data));
     17     for(i=2;i<=250000;i++)
     18     {                                                //筛选法
     19         if(data[i]==0)
     20             for(j=i+i;j<=500000;j+=i)
     21                 data[j]=1;
     22     }
     23     while(~scanf("%d",&n))
     24     {
     25         while(n--)
     26         {
     27             result=1;
     28             scanf("%d",&num);
     29             temp=num;
     30             r=1;
     31             for(i=2;i<=500000;i++)
     32             {
     33                 q=1;
     34                 if(!data[i])
     35                 {
     36                     p=1;
     37                     while(num%i==0)
     38                     {
     39                         p*=i;                               //公式
     40                         num/=i;
     41                         q+=p;
     42                     }
     43                     r*=q;
     44                     if(i>num)
     45                         break;
     46                 }
     47             }
     48             printf("%d\n",r-temp);
     49         }
     50     }
     51     return 0;
     52 }
     53 
     54 /*#include<iostream>
     55 #include<cmath>
     56 using namespace std;
     57 
     58 int count[50000];
     59 int flag[50000];
     60 int data[500000];
     61 
     62 int main()
     63 {
     64     int n;
     65     int num;
     66     int result;
     67     int temp;
     68     int i,j;
     69     int tip=0;
     70     memset(data,0,sizeof(data));
     71     for(i=2;i<=250000;i++)
     72     {
     73         if(data[i]==0)
     74             for(j=i+i;j<=500000;j+=i)
     75                 data[j]=1;
     76     }
     77     while(~scanf("%d",&n))
     78     {
     79         while(n--)
     80         {
     81             result=1;
     82             scanf("%d",&num);
     83             temp=num;
     84             memset(count,0,sizeof(count));
     85             memset(flag,0,sizeof(flag));
     86             for(i=2;i<=500000;i++)
     87             {
     88                 if(!data[i])
     89                 {
     90                     while(num%i==0)
     91                     {
     92                         flag[i]=1;
     93                         count[i]++;
     94                         num/=i;
     95                     }
     96                     if(flag[i])
     97                         result*=(pow(i,(count[i]+1))-1)/(i-1);               //公式:超时
     98                     if(i>num)
     99                         break;
    100                 }
    101             }
    102             printf("%d\n",result-temp);
    103         }
    104     }
    105     return 0;
    106 }
    107 */


    纠结了有蛮久,刚开始没有用筛选法,而且后面的公式写的方法不对,导致了超时,提交了N次,命中率伤不起了。

    看了下别人的解法,代码写的真整洁,真是自愧不如。

                法一:筛选法。。。。。空间换时间 

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 int wife[500010] = {0};
     6 
     7 int main( )
     8 {
     9     for( int i = 0; i < 500001; ++i )
    10     {
    11         wife[i] = 1;
    12     }
    13     for( int i = 2; i < 500001; ++i )
    14     {
    15         for( int j = 2; i * j < 500001; ++j )
    16         {
    17             wife[i*j] += j;
    18         }
    19     }
    20     int T;
    21     cin >> T;
    22     while( T-- )
    23     {
    24         int N;
    25         cin >> N;
    26         cout << wife[N] << endl;
    27     }
    28     return 0;
    29 }

                     法二:暴力

     1 #include <iostream>
     2 #include <cmath>
     3 
     4 using namespace std;
     5 
     6 int main( )
     7 {
     8     int T;
     9     cin >> T;
    10     while( T-- )
    11     {
    12         int N;
    13         cin >> N;
    14         int t = sqrt( N );
    15         int sum = 1;
    16         for( int i = 2; i <= t; ++i )
    17         {
    18             if( N % i == 0 )
    19             {
    20                 sum += i;
    21                 if( N / i != i )
    22                 {
    23                     sum += N / i;
    24                 }
    25             }
    26         }
    27         cout << sum << endl;
    28     }
    29     return 0;
    30 }

        约数的求和公式:

        数360的约数有多少个?这些约数的和是多少?

        【分析与解】  360分解质因数:360=2×2×2×3×3×5=23×32×5;

        360的约数可以且只能是2a×3b×5c,(其中a,b,c均是整数,且a为0~3,6为0~2,c为0~1).

    因为a、b、c的取值是相互独立的,由计数问题的乘法原理知,约数的个数为(3+1)×(2+1)×(1+1)=24.

        我们先只改动关于质因数3的约数,可以是l,3,32,它们的和为(1+3+32),所以所有360约数的和为(1+3+32)×2y×5w

        我们再来确定关于质因数2的约数,可以是l,2,22,23,它们的和为(1+2+22+23),所以所有360约数的和为(1+3+32)×(1+2+22+23)×5w

        最后确定关于质因数5的约数,可以是1,5,它们的和为(1+5),所以所有360的约数的和为(1+3+32)×(1+2+22+23)×(1+5).

        于是,我们计算出值:13×15×6=1170.

        所以,360所有约数的和为1170.

        评注:我们在本题中分析了约数个数、约数和的求法.下面我们给出一般结论:

        I.一个合数的约数的个数是在严格分解质因数之后,将每个质因数的指数(次数)加1后

    所得的乘积.如:1400严格分解质因数后为23×52×7,所以它的约数有(3+1)×(2+1)×(1+1)=4×3×2=24个.(包括1和它自身)

    Ⅱ.约数的和是在严格分解质因数后,将M的每个质因数最高次幂的所有约数的和相乘所得到的积.如:21000=23×3×53×7,所以21000所有约数的和为(1+2+22+23)×(1+3)×(1+5+52+53)×(1+7)=74880.







                If you have any questions about this article, welcome to leave a message on the message board.



    Brad(Bowen) Xu
    E-Mail : maxxbw1992@gmail.com


  • 相关阅读:
    JS
    Python之缩进块
    Python快捷键
    Python介绍
    SOAP UI-----测webservice接口
    jmeter分布式压测(多台电脑一起压测)
    jmeter操作数据库
    jmeter压测
    jmeter关联
    jmeter参数化
  • 原文地址:https://www.cnblogs.com/XBWer/p/2554096.html
Copyright © 2011-2022 走看看