探索合數世紀題解

  • 2020 年 5 月 30 日
  • 筆記

探索合數世紀

問題描述

  若一個世紀的100年號中不存在一個素數,則稱這個世紀為合數世紀。求第n個合數世紀(公元0年起始)。

輸入描述

  輸入n,為整數

輸出描述

  輸出合數世紀起始與結束年份,用空格隔開

樣例輸入

1

樣例輸出

1671800 1671899

 

  這道題是一道遍歷題,遍歷0-99,沒有合數世紀就累加100,訣竅在於如何讓代碼的效率更好。

  我首先想到的是,用for循環對0到99進行素數判斷,只要有一個素數就認為這個世紀不行,判斷素數我用的代碼如下

1 int judge(int n)
2 {
3     int sum=0;
4     for(int i=2;i<n/2;i++)
5     {
6         if(num%i==0)    return 0;
7     }
8     return 1;
9 }

  於是問題出現了,判斷素數的代碼上面這個已經是我能想到的效率最快的一個了,但還是不行,時間複雜度約為為O(n/2),隨着n越大,循環次數越多,時間用得也越多,也就導致了,第一個合數世紀超過三秒還是判斷不出來,我們以1秒的標準要求自己。

  查了一下資料,我發現了一個時間複雜度更低的算法。

  我原先是打算判斷是不是素數,而我現在我打算判斷是不是合數,代碼如下

1 int judge(int n)
2 {
3     int sum=0;
4     for(int i=2;i*i<=n;i++)
5     {
6         if(n%i==0)  return 1;
7     }
8     return 0;
9 }

  很巧妙的一個判斷是否是合數,時間複雜度為最大為O(n^0.5),遠遠小於O(n/2)。

  於是,我用這個算法打造了一個程序,如下

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int judgecompos(int n)    //在n~n+99之內進行素數累加
 5 {
 6     int count=0;
 7     for(int i=n+1;i<n+100;i+=2)    //省去偶數,節約時間
 8     {
 9         for(int j=2;j*j<=i;j++)
10         {
11             if(i%j==0)
12             {
13                 count++;    //素數累加
14                 break;
15             }
16         }
17     }
18     if(count==50)   return 1;
19     else    return 0;
20 }
21 
22 int main()
23 {
24     int begin=0,n=0;
25     cin>>n;
26     for(int i=1671700;;i+=100)    //這裡取了一個巧,i從1671700開始,i從0開始也是沒問題的
27     {
28         if(judgecompos(i)==1)
29         {
30             begin++;
31         }
32         if(n==begin)
33         {
34             cout<<i<<' '<<i++99<<endl;
35            break;
36         }
37     }
38     return 0;
39 }

  相比於原來的素數判斷來說,這的是節省了很多時間,如果你有更好的代碼和思路,歡迎交流!