JZOJ 4725. 质数序列

Description
由于去NOI的火车“堵”了数不清时间,小Z和小D打完ETG,闲着无聊开始看今年的JSOI省选题,并尝试着修改题目:
对于一个长度为L ≥ 2的序列,X:x1,x2,...,xL ,如果满足对于任意的1 ≤ i < j ≤ L,均有 xi+xj为质数,则他们把X称为一个“质数序列”。
现在有一个长度为N的序列,A:a1,a2,...,aN ,他希望从中选取一个包含元素最多的子序列,使得这个子序列是一个质数序列。如果元素个数相同,则使子序列之和最大(在此意义下,保证有唯一解)。
因为他们还要xx,所以这个任务就交给你了。
Input
输入第一行包含一个正整数 N。
接下来一行包含N个正整数,依次描述 a1,a2,...,aN。
Output
输出两行,第一行一个整数L,表示最长质数子序列的长度,第二行L个整数从小到大输出,表示最长质数子序列(元素个数相同,则使子序列之和最大)。
Sample Input
3
2 3 4
Sample Output
2
3 4
Data Constraint
对于30%的数据满足N<=100 。
对于60%的数据满足N<=1000 ,ai<=5,000,000 。
对于100%的数据满足N<=1000 ,1<=ai<=15,000,000 。
 
做法:思考一下就会发现,本体其实只有3种情况
{
  若序列中不存在1或只有1个1,那么最长的长度一定为2,此时只要找两个最大的就好
  若序列中存在2个1,那么寻找序列中最大的一个能和1组成质数的数,若找不到,视作情况1
  若序列中存在3个及以上的1,那么参考情况2,若找不到,输出1的个数和所有的1即可
}
 
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cmath>
 4 #include <cstring>
 5 #define N 1007
 6 #define M 30000007
 7 #define LL long long
 8 using namespace std;
 9 int n,zs[M/2],T1;
10 LL a[N],sum,q,p;
11 bool b[M + 20];
12 
13 void Pre_work(){
14     for(int i=2;i<=M;i++){
15         if(!b[i])    zs[++zs[0]]=i;
16         for(int j=1;j<=zs[0];j++)
17             if((LL)i*zs[j]<=M-5)    b[i*zs[j]]=1;
18             else break;
19     }
20 }
21 
22 int main(){
23     Pre_work();
24     memset(a,0,sizeof(a));
25     q=0,p=0,sum=0;
26     scanf("%d",&n);
27     for(int i=1;i<=n;i++){
28         scanf("%lld",&a[i]);
29         if (a[i]==1) T1++;
30     }
31     if (T1>2){
32         for (int i=1;i<=n;i++)
33             if (!b[a[i]+1])    q=max(q,a[i]);
34         if (q!=0 && q!=1){
35             printf("%d\n",T1+1);
36             for (int i=1;i<=T1;i++)    printf("1 ");
37             printf("%lld",q);
38         }
39         else{
40             printf("%d\n",T1);
41             for (int i=1;i<=T1;i++)    printf("1 ");
42         }
43         return 0;
44     }
45     else if (T1==2){
46         for (int i=1;i<=n;i++)
47             if (!b[a[i]+1])    q=max(q,a[i]);
48         if (q!=0 && q!=1){
49             printf("%d\n",T1+1);
50             for (int i=1;i<=T1;i++)    printf("1 ");
51             printf("%lld",q);
52             return 0;
53         }
54     }
55     else{
56         for(int i=1;i<n;i++)
57             for(int j=i+1;j<=n;j++)
58                 if (!b[a[i]+a[j]]){
59                     if(a[i]+a[j]>sum){
60                         q=a[i],p=a[j];
61                         sum=q+p;
62                     }
63                 }
64         printf("2\n");
65         if (q>p) swap(q,p);
66         printf("%lld %lld", q, p);
67     }
68 }
View Code

 

转载于:https://www.cnblogs.com/traveller-ly/p/9525838.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值