质数序列(prime)
【问题描述】
由于去NOI的火车“堵”了数不清时间,小Z和小D打完ETG,闲着无聊开始看今年的JSOI省选题,并尝试着修改题目:
对于一个长度为L≥2的序列,
,如果满足对于任意的1≤i<j≤L,均有为质数,则他们把X称为一个“质数序列”。
现在有一个长度为N的序列,
,他希望从中选取一个包含元素最多的子序列,使得这个子序列是一个质数序列。如果元素个数相同,则使子序列之和最大(在此意义下,保证有唯一解)。
因为他们还要xx,所以这个任务就交给你了。
【输入格式】
从文件 prime.in 中读入数据。
输入第一行包含一个正整数 N。
接下来一行包含N个正整数,依次描述。
【输出格式】
输出到文件 prime.out 中。
输出两行,第一行一个整数L,表示最长质数子序列的长度,第二行L个整数从小到大输出,表示最长质数子序列(元素个数相同,则使子序列之和最大)。
【样例输入】
3
2 3 4
【样例输出】
2
3 4
【数据规模与约定】
对于30%的数据满足。N ≤100
对于60%的数据满足,N≤1000
对于100%的数据满足,N≤1000
考场:
预计:20实际:0
想到了其实不选1的话,最多只能选择2个数,所以直接就输出了个"2",然后就开始挨个枚举加和是不是质数,结果,过了样例,然后就寄了
然后代码写成了这个东西
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=15e6+50;
int n;
int a[N];
bool cmp(const int &x,const int &y){
return x<y;
}
void read(int &x){
char s=getchar();
while(s<'0'||s>'9'){
s=getchar();
}
while(s>='0'&&s<='9'){
x=x*10+s-'0';
s=getchar();
}
}
inline bool prime(int x){
bool flag=true;
for(int i=2;i<=sqrt(x);i++){
if(x%i==0){
flag=false;
break;
}
}
if(x>=2&&flag){
return true;
}
return false;
}
signed main(){
freopen("prime.in","r",stdin);
freopen("prime.out","w",stdout);
read(n);
for(int i=1;i<=n;i++){
read(a[i]);
}
sort(a+1,a+n,cmp);
printf("2\n");
for(int i=n;i>=1;i--){
for(int j=i-1;j>=1;j--){
if(prime(a[i]+a[j])){
printf("%lld %lld\n",a[j],a[i]);
return 0;
}
}
}
return 0;
}
正解:
如果所有元素都大于1,那么Lmax = 2(奇偶性分析一下即可)
显然所有的1全选择不会比选择一部分1要劣。
O(N^2)枚举,判断一下即可。
首先来看一下考场想到的性质
当两个数都大于1时
奇数+奇数=偶数(>2,不是质数)
偶数+偶数=偶数(不是质数)
所以当原序列中没有1时,原序列只可能有两个数且一个是奇数一个是偶数。
若序列中有1时,1+1=2,2是质数。设cnt为序列中1的个数
也就是有1就开始选(1>=2)
当cnt<2时,序列中最多可能有两个元素一奇一偶,所以直接可以用两重for循环分别枚举奇数和偶数,枚举出所有的排列判断它们的和是不是质数,最后保留最优解就行了。
当cnt>=2时,为了保证序列最长所有的1肯定是要保留的,此时序列中还可以再加进来一个偶数,我们再枚举所有偶数判断更新就行了。
Code:
long long这道题别乱开,容易炸空间(亲身体验)
#include<bits/stdc++.h>
using namespace std;
const int MAXA=30000001;
int n,x,tmp,a[1001],ans[3],pri[MAXA];
bool vis[MAXA],flg;
void euler(int m){
int cnt=0;
vis[1]=1;
for(int i=2;i<=m;i++){
if(!vis[i]){
pri[++cnt]=i;
}
for(int j=1;i*pri[j]<=m&&j<=cnt;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0){
break;
}
}
}
}
int sit1(){
for(int i=n;i>=x+1;i--){
if(!vis[a[i]+1]){
return a[i];
}
}
return 0;
}
void sit2(){
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(!vis[a[i]+a[j]]){
if(a[i]