列表

详情


NC17356. Coprime

描述

    小团当上了幼儿园园长,他想把n个小朋友排成一个圈做游戏。小朋友们编号是1到n。小团发现,如果把两个编号互质的小朋友放在相邻的位置,那么这两个小朋友就会打架。小团希望打架的小朋友对数越少越好。能不能帮小团找到一个这样的安排?

输入描述

第一行一个整数T表示数据组数。

然后T行,每行一个整数n(3≤n≤1,000,000)。

1≤T≤2000
Σn≤1,000,000

输出描述

输出T行,第i行n个整数p1, p2, p3, ...,pn。pi表示第i个位置小朋友的编号,第i个位置和i mod n+1位置的小朋友相邻。如果有多解,输出任意解即可。

示例1

输入:

1
5

输出:

1 2 4 3 5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 173ms, 内存消耗: 13000K, 提交时间: 2020-03-24 22:35:18

#include<iostream>
#include<algorithm>
#include<vector>
#include<cassert>
using namespace std;
#define MAXNUM 1111111
#define ll long long
#define rep(i,start,end) for(int i=start;i<end;i++)
vector<ll> prime;
bool isprime[MAXNUM];
ll n;
void per()
{
	rep(i,1,n+1)
	isprime[i]=1;
	isprime[0]=isprime[1]=0;
	for(int i=2;i<=n;i++)
	{
		if(isprime[i])
		prime.push_back(i);
		for(int j=i*2;j<=n;j+=i)
		isprime[j]=0;
	}
}
vector<int> middle;
int before,before2;
void getit()
{
	middle.clear(),before=before2=-1;
	auto iter=++prime.begin();
	for(;iter!=prime.end();iter++)
	if((*iter*4)<=n)
	middle.push_back(*iter);
	else break;
	auto a=iter;
	int now=0;
	while(iter!=prime.end()&&*iter*2<=n&&*iter*3<=n)
	iter++,now++;
	if((now&1)&&middle.size())
	before2=*(a++);
	if(a!=prime.end()&&*a*2<=n)
	before=*a;
	if(iter!=prime.end()&&*iter*2<=n)
	before=*iter; 
}
int isused[MAXNUM];
void p(int k)
{
	isused[k]=1,printf("%d ",k);
}
void printit(int k)
{
	for(int i=k;i<=n;i+=k)
	if(!isused[i])
	p(i);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%lld",&n);
		prime.clear();
		per();
		getit();
		rep(i,1,n+1)
		isused[i]=0;
		auto iter2=++prime.begin();
		while(*iter2*4<=n)
		iter2++;
		for(auto iter=iter2;iter!=prime.end();iter++)
		{
			if(*iter==before||*iter==before2)
			continue;
			if(*iter*2<=n)
			isused[*iter*2]=1;
			if(*iter*3<=n)
			isused[*iter*3]=1;
		}
		if(before!=-1)
		{
			isused[before*2]=1;
			printit(before);
			p(before*2);
		}
		if(before2!=-1)
		{
			isused[before2*2]=isused[before2*3]=1;
			p(before2*2);
			printit(before2);
			p(before2*3);
		}
		for(int k:middle)
		{
			p(k*2);
			isused[k*4]=1;
			printit(k);
			p(k*4);
		}
		printit(2);
		bool type=1;
		for(auto iter=iter2;iter!=prime.end();iter++)
		{
			if(*iter==before||*iter==before2)
			continue;
			if(*iter*2<=n&&type)
			p(*iter*2);
			else if(*iter*3<=n&&!type)
			p(*iter*3);
			printit(*iter);
			if(*iter*2<=n&&!type)
			p(*iter*2);
			else if(*iter*3<=n&&type)
			p(*iter*3);
			type=!type;
		}
		printf("1\n");
	}
}

上一题