sakiko要构造一个长度为 nnn 的排列 ppp ,使得每一个 pi+i (1≤i≤n)p_i+i\ (1\leq i\leq n)pi+i (1≤i≤n) 都是质数。
排列的定义为:长度为 nnn 的数组,其中 1−n1-n1−n 每个数字在数组中各出现一次。
输入描述:
第一行输入一个整数 n(1≤n≤106)n(1 \leq n \leq 10^6)n(1≤n≤106) 表示数组长度。
输出描述:
输出 nnn 个整数表示答案,如果有多种解法,则输出任意一种。 若无解则输出 -1。
示例1
输入
3
输出
1 3 2
切比雪夫定理:对于一个大于1的正整数,在(a,2a]内总有一个素数
思路:在序列1.2.3...n中,对于任意一个子序列,若能使其第一个数和最后一个数相加等于一个素数,那么这一段的构造为:从最后一个数倒着把他们放入构造数组中。
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
int prime[N];
bool isprime[N];
int cnt=0;
void eular(int n)//欧拉筛法筛出所有素数
{
memset(isprime,true,sizeof(isprime));
isprime[1]=false;
for(int i=2;i<=n;i++)
{
if(isprime[i])prime[cnt++]=i;
for(int j=0;prime[j]*i<=n&&j<=cnt;j++)
{
isprime[i*prime[j]]=false;
if(i%prime[j]==0)break;
}
}
}
int main()
{
int n;
cin>>n;
eular(2*n);//欧拉筛
int i=n;
int a[n+1];
while(i>=1)
{
int minp=i+1;
while(!isprime[minp])minp++;//找到大于n的第一个素数
int mini=minp-i;
for(int j=mini;j<=i;j++){a[j]=minp-j;}//存入数组
i=mini-1;//处理前面未处理的部分
}
for(int i=1;i<=n;i++)cout<<a[i]<<" ";//输出
}