(代码原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即可),用到“线性素数法”(很快地找全体素数),代码如下:
- const int M = 3000500;
- int p[400010], pNum;
- bool f[M];
- void Prime()
- {
- int i, j;
- for(i = 2; i < M; i++) {
- if(!f[i]) { p[pNum++] = i; }
- for(j = 0; j < pNum && p[j] * i < M; j++ ) {
- f[p[j]*i] = 1;
- if(!(i%p[j]))
- break;
- }
- }
- }
举个例子:
比如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;}
运行出来不对,不知道为何。暂时搁着(...ε=(´ο`*)))唉)