最强素数
题目描述
小李在你帮助之下轻松战胜了他的同学们,于是满怀恶意的同学出了一个题目来为难小李,作为小李神一样的队友,你又要出力了。
素数41能写成连续6个素数之和:41=2+3+5+7+11+13。
现在要求n以内的素数中,能表示为最多连续素数之和的那个数,如果有多个答案,请输出最大的那个素数。
输入
仅一行,一个整数n(1<=n<=1000000)。
输出
输出就一个整数,为所求的能表示为最多连续素数和的那个素数。
样例输入
复制样例数据
100
样例输出
41
提示
41=2+3+5+7+11+13
一开始我看到1e6这么大的数认为肯定是不能暴力搜索的,所以我觉得小于n最大的符合条件的数一定是从第一个素数累加得到的,但经过一竖列的"答案错误",就知道肯定有问题,于是暴搜了一下,答案的确不一样,并且暴搜没有超时,O(n)loglogn的埃氏筛还是很有效的.
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int vis[1100000] = { 0 }, primeall[1100000];
int vis2[1100000] = { 0 },choose1[1100000];
int cnt = 0;
void prime() //进行素数打表并记录到primeall数组里
{
for (int i = 2; i < 1100000; i++)
{
if (vis[i] == 0) //利用vis数组对所有素数进行标记
{
primeall[cnt++] = i;
for (int j = i*2; j < 1100000; j+=i)
{
vis[j] = 1;
}
}
}
}
typedef struct m //创建结构体便于后一步比较
{
int sum, count;
}M;
int cmp(M a, M b)
{
if (a.count == b.count)
return a.sum > b.sum; //先比较count即组成这个数的素数个数,在比较
else //这个数,最后输出的第一个的sum一定是最大的
return a.count > b.count;
}
int main()
{
prime();
M s[30005];
int n;
scanf("%d", &n);
int mmp = 0;
int i = 0,maxn=0;
for (int i = 0; i < cnt; i++)
{
int sum = 0;
for (int j = i; j < cnt; j++)
{
sum += primeall[j];
if (sum > n)
break;
if (!vis[sum])
{
if (sum >= maxn)
{
maxn = sum;
s[mmp].sum = maxn, s[mmp++].count = j - i + 1;
}
}
}
}
sort(s, s + mmp, cmp);
printf("%d\n", s[0].sum);
return 0;
}