【蓝桥杯真题-线性素数法+枚举法】等差素数列

(代码原po):

http://blog.csdn.net/y1196645376/article/details/69718192

#include <algorithm> #include <string.h>#include <iostream>#include <stdio.h>#include <string>#include <vector>#include <queue>#include <map>#include <set>using namespace std;const long long N = 1000010;int dp[N]={1,1,0};int prim[N],tot = 0;void init(){ for(long long i = 2 ; i < N ; i ++) { if(dp[i])continue; prim[tot++]=i; for(long long j = i ; j * i < N ; j ++){ dp[i*j] = 1; } }}int main(){ init(); printf("%d\n",tot); for(int i = 1 ; i*10 < N ; i ++){ for(int j = 0 ; j < tot ; j ++){ int flag = 1,temp = prim[j]; for(int k = 1 ; k < 10 ; k ++) { if(temp + i >= N || dp[temp + i] == 1){ flag = 0;break; }else{ temp = temp + i; } } if(flag == 1){ printf("%d %d\n",i,prim[j]); return 0; } } } return 0;}//210 199 学到的点: ①首先,这道题应该去求全体素数序列(到1000000即可),用到“线性素数法”(很快地找全体素数),代码如下:
  1. const int M = 3000500;  
  2. int p[400010], pNum;  
  3. bool f[M];  
  4. void Prime()  
  5. {  
  6.     int i, j;  
  7.     for(i = 2; i < M; i++) {  
  8.         if(!f[i]) { p[pNum++] = i; }  
  9.         for(j = 0; j < pNum && p[j] * i < M; j++ ) {  
  10.             f[p[j]*i] = 1;  
  11.             if(!(i%p[j]))  
  12.                 break;  
  13.         }  
  14.     }  
  15. }  
这其实比原Po给的代码还要快。因为:最后一个if语句中,

举个例子:

比如i = 9,现在素数是2 3 5 7

进入第二重循环了,f[2 * 9] = 1;f[3 * 9] = 1;

这个时候9%3==0,要跳出了,为什么不做f[5* 9] =1;呢?

因为5 * 9 可以用3 * 15来代替,如果这个时候你计算了,那么到i=15的时候这个数还会被重复计算一次,所以这里大量避免了重复运算,所以也就节省了时间。

 

这里总结一句话就是,一个大的合数和这个能除尽的质数的乘积,一定能被一个比起小的质数和合数更大的合数乘积来代替。

不懂的时候想想 5*9 = 5*3*3 = 3*15就是这个道理。

 这也是线性筛法算质数表的关键所在。

②学到枚举了。暴力枚举其实没有想象中那么简单,一定是要结合题意,就算是枚举,也是需要在for语句中根据题意增加一些约束条件的。

比如这里,10个数的(递增)等差数列的公差*10一定<最大数,然后就是找起点,对于每个起点去依次迭加公差,每一次的迭加都要符合

是素数的条件并且小于1000000(注意&& || 别用混。。)。

(对每一个起点)迭加九次,比较关键的地方在于用flag去判断循环结束后这个循环满足条件不,满足,flag仍=1,那么

这个公差即所求。

PS:后半部分自己写的代码是

for(int k=1;k*10<1000000;k++)    {    	for(int i=0;i<pos;i++)    	{    		int flag=1;    		int temp=prim[i];    		for(int j=0;j<9;j++)    		{    			if(temp+k>=1000000 || f[temp+k]==1)    			{    				flag=0;    				break;				}				else{					temp=temp+k;				}			}			if(flag==1)			{cout<<k<<endl;			 return 0;			}		}		    			}	return 0;}


运行出来不对,不知道为何。暂时搁着(...ε=(´ο`*)))唉)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值