POJ中和質數相關的三個例題(POJ 226二、POJ 273九、POJ 3006)

      質數(prime number)又稱素數,有無限個。一個大於1的天然數,除了1和它自己外,不能被其餘天然數整除,換句話說就是該數除了1和它自己之外再也不有其餘的因數;不然稱爲合數。
      最小的質數是2。ios

【例1】Goldbach's Conjecture (POJ 2262)

Description編程

In 1742, Christian Goldbach, a German amateur mathematician, sent a letter to Leonhard Euler in which he made the following conjecture:數組

Every even number greater than 4 can beless

written as the sum of two odd prime numbers.ide

For example:函數

8 = 3 + 5. Both 3 and 5 are odd prime numbers.測試

20 = 3 + 17 = 7 + 13.this

42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23.spa

Today it is still unproven whether the conjecture is right. (Oh wait, I have the proof of course, but it is too long to write it on the margin of this page.)3d

Anyway, your task is now to verify Goldbach's conjecture for all even numbers less than a million.

Input

The input will contain one or more test cases.

Each test case consists of one even integer n with 6 <= n < 1000000.

Input will be terminated by a value of 0 for n.

Output

For each test case, print one line of the form n = a + b, where a and b are odd primes. Numbers and operators should be separated by exactly one blank like in the sample output below. If there is more than one pair of odd primes adding up to n, choose the pair where the difference b - a is maximized. If there is no such pair, print a line saying "Goldbach's conjecture is wrong."

Sample Input

8

20

42

0

Sample Output

8 = 3 + 5

20 = 3 + 17

42 = 5 + 37

      (1)編程思路1。

      對每一個輸入的n,從小到大依次對3~n/2之間的奇數i進行窮舉,若i和n-i均是質數,則找到一組解,退出窮舉。

判斷一個數num是否爲質數的方法是:用2~ 中的每個整數m去除num,若某一個m能整除num,則num不是質數;不然,m是質數。

      (2)源程序1。

#include <iostream>

#include <cmath>

using namespace std;

bool isPrime(int num)

{

    int m;

    if(num==2) return true;

    for(m=2;m<=(int)sqrt((double)num);m++)

        if (num%m==0)

         return false;

    return true;

}

int main()

{

    int n,i;

    while(cin>>n&&n)

       {

       for(i=3;i<=n/2;i+=2)

          {

          if(isPrime(i) && isPrime(n-i))

                {

             cout<<n<<" = "<<i<<" + "<<n-i<<endl;

             break;

                }

          }

       }

    return 0;

}

      (3)編程思路2。

      上面的程序在窮舉時,對每一個窮舉的整數i,都要調用函數isPrime(i) 和isPrime(n-i)來判斷i和n-i是否爲質數。實際上,能夠預先生成一個斷定數組flag[1000000],而且爲了節省存儲空間,可將flag數組定義爲char類型(每一個元素只佔一個字節)。元素flag[i]==’1’表示整數i是質數;flag[i]==’0’表示整數i不是質數。

      初始化數組flag的全部元素都爲’1’,而後採用Eratosthenes篩法進行處理。

       Eratosthenes篩法的基本思想是:把某範圍內的天然數從小到大依次排列好。宣佈1不是質數,把它去掉;而後從餘下的數中取出最小的數,宣佈它爲質數,並去掉它的倍數。在第1步以後,獲得質數2,篩中只包含奇數;第2步以後,獲得素數3,一直作下去,直到篩子爲空時結束。

      採用這個思想,用以下循環完成對flag數組的設置。

       for(i=2;i<1000000;i++)      // 用篩法構建質數表

       {

        if (flag[i]=='1')

                     for (j=2*i;j<1000000;j+=i)

                            flag[j]='0';

    }

      (4)源程序2。

#include <iostream>

using namespace std;

int main()

{

    char flag[1000000];

       int i,j,n;

    for (i=2;i<1000000;i++)

              flag[i]='1';

       for(i=2;i<1000000;i++)      // 用篩法構建質數表

       {

        if (flag[i]=='1')

                     for (j=2*i;j<1000000;j+=i)

                            flag[j]='0';

    }

    while(cin>>n&&n)

       {

       for(i=3;i<n;i++)

          {

          if(flag[i]=='1' && flag[n-i]=='1')

                {

             cout<<n<<" = "<<i<<" + "<<n-i<<endl;

             break;

                }

          }

       }

    return 0;

}

      將源程序1和2分別提交給POJ評判系統,可獲得如圖1所示的評判結果。從結果能夠看出,源程序2的執行效率比源程序1高,固然所佔用的存儲空間也比源程序1要多。能夠說是「用空間換時間」。  

圖1  POJ給出的評判結果

 

【例2】Sum of Consecutive Prime Numbers (POJ 2739)

Description

Some positive integers can be represented by a sum of one or more consecutive prime numbers. How many such representations does a given positive integer have? For example, the integer 53 has two representations 5 + 7 + 11 + 13 + 17 and 53. The integer 41 has three representations 2+3+5+7+11+13, 11+13+17, and 41. The integer 3 has only one representation, which is 3. The integer 20 has no such representations. Note that summands must be consecutive prime numbers, so neither 7 + 13 nor 3 + 5 + 5 + 7 is a valid representation for the integer 20.

Your mission is to write a program that reports the number of representations for the given positive integer.

Input

The input is a sequence of positive integers each in a separate line. The integers are between 2 and 10 000, inclusive. The end of the input is indicated by a zero.

Output

The output should be composed of lines each corresponding to an input line except the last zero. An output line includes the number of representations for the input integer as the sum of one or more consecutive prime numbers. No other characters should be inserted in the output.

Sample Input

2

3

17

41

20

666

12

53

0

Sample Output

1

1

2

3

0

0

1

2

      (1)編程思路1。

      先將10000之內的全部質數求出來保存到數組prime中,並記下質數的個數len。

      對於給定的測試數據n,用二重循環求出全部的連續質數和等於n的種數cnt。

      (2)源程序1。

#include <iostream>

#include <cmath>

using namespace std;

bool isPrime(int num)

{

    int m;

    if(num==2) return true;

    for(m=2;m<=(int)sqrt((double)num);m++)

        if (num%m==0)

         return false;

    return true;

}

int main()

{

    int prime[2000],i,j,len=0,n,cnt,sum;

    for(i=2;i<10000;i++)

       {

        if(isPrime(i))

            prime[len++]=i;

    }

    while (cin>>n && n!=0)

       {

        cnt=0;

        for(i=0;i<len;i++)

              {

            sum=0;

            for(j=i;j<len;j++)

                     {

                sum+=prime[j];

                if(sum>n)

                    break;

                else if(sum==n)

                            {

                    cnt++;

                    break;

                }

            }

        }

        cout<<cnt<<endl;

    }

    return 0;

}

      (3)編程思路2。

       採用打表的方法。先用二重循環構造好答案表。

    for(i=0;i<len;i++)          

       {

        sum=0;

        for(j=i;j<len;j++)

              {

            sum+=prime[j];

            if(sum>10000) break;

                     ans[sum]++;      //  連續和爲sum的種數加1

             }

       }

      對於給定的測試數據n,直接查表ans[n]便可。

      (4)源程序2。

#include <iostream>

using namespace std;

int main()

{

    int flag[10000]={0},prime[2000],ans[10001]={0};

       int i,j,len=0,n,sum;

    for(i=2;i<10000;i++)           // 構造質數表

       {

        if (flag[i]==0)

              {

                     prime[len++]=i;

                     for (j=2*i;j<10000;j+=i)

                            flag[j]=1;

              }

    }

    for(i=0;i<len;i++)            // 構造答案表

       {

        sum=0;

        for(j=i;j<len;j++)

              {

            sum+=prime[j];

            if(sum>10000) break;

                     ans[sum]++;

             }

       }

    while (cin>>n && n!=0)

       {

        cout<<ans[n]<<endl;

    }

    return 0;

}

 【例3】Dirichlet's Theorem on Arithmetic Progressions (POJ 3006)

Description

If a and d are relatively prime positive integers, the arithmetic sequence beginning with a and increasing by d, i.e., a, a + d, a + 2d, a + 3d, a + 4d, ..., contains infinitely many prime numbers. This fact is known as Dirichlet's Theorem on Arithmetic Progressions, which had been conjectured by Johann Carl Friedrich Gauss (1777 - 1855) and was proved by Johann Peter Gustav Lejeune Dirichlet (1805 - 1859) in 1837.

For example, the arithmetic sequence beginning with 2 and increasing by 3, i.e.,

2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98, ... ,

contains infinitely many prime numbers

2, 5, 11, 17, 23, 29, 41, 47, 53, 59, 71, 83, 89, ... .

Your mission, should you decide to accept it, is to write a program to find the nth prime number in this arithmetic sequence for given positive integers a, d, and n.

Input

The input is a sequence of datasets. A dataset is a line containing three positive integers a, d, and n separated by a space. a and d are relatively prime. You may assume a <= 9307, d <= 346, and n <= 210.

The end of the input is indicated by a line containing three zeros separated by a space. It is not a dataset.

Output

The output should be composed of as many lines as the number of the input datasets. Each line should contain a single integer and should never contain extra characters.

The output integer corresponding to a dataset a, d, n should be the nth prime number among those contained in the arithmetic sequence beginning with a and increasing by d.

FYI, it is known that the result is always less than 106 (one million) under this input condition.

Sample Input

367 186 151

179 10 203

271 37 39

103 230 1

27 104 185

253 50 85

1 1 1

9075 337 210

0 0 0

Sample Output

92809

6709

12037

103

93523

14503

2

899429

      (1)編程思路。

      定義數組char flag[1000000]用於質數的斷定。元素flag[i]==’1’表示整數i是質數;flag[i]==’0’表示整數i不是質數。

      對於輸入的測試數據a、d和n,採用循環找到第n個質數在原等差數列中位置i。

       count = 0; 

       for(i=0;count<n;i++) 

          { 

           if(flag[a+d*i]=='1') 

              count++; 

          } 

      (2)源程序。

#include <iostream> 

using namespace std; 

int main() 

    int a,d,n,i,j,count; 

    char flag[1000000];

    for (i=2;i<1000000;i++)

              flag[i]='1';

       for(i=2;i<1000000;i++)      // 用篩法構建質數表

       {

        if (flag[i]=='1')

                     for (j=2*i;j<1000000;j+=i)

                            flag[j]='0';

    }

    flag[1]='0'; 

    while(cin>>a>>d>>n && a+d+n!=0) 

       { 

       count = 0; 

       for(i=0;count<n;i++) 

          { 

           if(flag[a+d*i]=='1') 

              count++; 

          } 

       cout<<a+d*(i-1)<<endl; 

       } 

    return 0; 

}  

相關文章
相關標籤/搜索