探索合数世纪题解
探索合数世纪
问题描述
若一个世纪的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 }
相比于原来的素数判断来说,这的是节省了很多时间,如果你有更好的代码和思路,欢迎交流!