【JZOJ4725】质数序列 题解(数学)

题目大意:质数序列是指这个序列中任意两个数的和均为质数。先给出一个序列${a_{n}}$,从中取出元素构成最长质数序列,问其长度并输出序列。若长度相同则求和最大的序列。保证答案唯一。

-----------------

小小的数学题。

1.偶数+偶数不是质数,奇数+奇数不是质数。但某些偶数+奇数($1$)是质数。所以这个序列中$1$是个很关键的因素。

我们进行分类讨论:

1.若序列中$1$的个数大于$2$

  长度为所有$1$的个数。

  所有$1$再加一个偶数。(此偶数+$1$后为质数)

2.若序列中$1$的个数等于$2$

  两个$1$。

  两个$1$加一个偶数。

  偶数+奇数。

3.若序列中$1$的个数小于$2$

  偶数+奇数。

质数需要线性筛预处理。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
bool vis[30000010];
int n,p[1000005],c,a[100005],m,t,s,b;
signed main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        m=max(m,a[i]);
        if (a[i]==1) c++;
    }
    for (int i=2;i<=m;i++)
    {
        if (!vis[i]) p[++t]=i;
        for (int j=1;j<=t&&i*p[j]<=m;++j)
        {
            vis[i*p[j]]=1;
            if (i%p[j]==0) break;
        }
    }
    sort(a+1,a+n+1);
    if (c>1)
    {
        for (int i=n;i>=1;i--)
        {
            if (!vis[a[i]+1])
            {
                printf("%d\n",c+1);
                for (int j=c;j>=1;j--) printf("1 ");
                printf("%d ",a[i]);
                return 0;
            }
        }
        for (int i=1;i<=c;i++) printf("1 ");
        return 0;
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<i;j++)
            if (!vis[a[i]+a[j]]&&a[i]+a[j]>a[s]+a[b]) s=i,b=j;
    if (!a&&!b)
    {
        for (int i=n;i>=1;i--)
            if (!vis[a[i]]) {printf("1\n%d",a[i]);return 0;}
        printf("0");
    }
    printf("2\n%d %d",a[b],a[s]);
    return 0;
}

 

posted @ 2020-05-01 21:23  我亦如此向往  阅读(321)  评论(0编辑  收藏  举报