codeforces 题目 Permutations & Primes

目录

题目:

题目描述:

思路:

AC代码:


题目:

题目描述:

对于每个案例,给你一个 n

目标:让你找出 1 到 n 的全排列的一种,使得里面所有区间的素性个数总和最多。

判断一个区间 ( l , r ) 是否为素性,看 MEX( a_l , a_{l+1} ......a_r )是否为素数,即是看他缺少的数中的最小正整数是否为素数( 如:1 5 4 2 缺少的最小正整数为 3 ,是素数即这个区间具有素性 )。

思路:

这道题上手先试试,我们会发现,1 的位置非常重要,如果一个区间没有 1 的话,那么最小正整数就是 1 ,必定不是素性区间。所以我们尽可能让更多的区间拥有 1 ,那么 1 就应该放在中间(即 n / 2  + 1 的位置),此时拥有1的区间个数是最多的。

为什么这个时候包含 1 的区间是最多的?请看下图

我取 1 左边的任意一个括号和 1 右边的任意一个括号都能形成一个包含 1 的区间,所以

包含1的区间总数 = ( 1 左边个数 + 1 )*( 1 右边个数 + 1 )

在 1 左右个数的和一定的情况下那一定是 “ 差小积大 ” 啦,所以 1 左边有 n / 2 个数的时候包含 1 的区间个数最多(即 1 要放到 n / 2  + 1 的位置)

除此之外,我们发现 2 ,3 都是质数,所以如果区间再有 1 的情况下缺少 2 或 3 ,必定就是素性区间。所以为了更难让区间里面有 2 或 3 ,我们应该把 2 ,3 放两边。在这样的情况下( 2 ... 1 ... 3 )包含 1 的区间中只有长度为 n 的时候(即此时区间的最小正整数为 n + 1 时)可能不满足条件,其他都是素性区间,发现此时为最优方案。

思路有了,具体操作请看AC代码

AC代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int N = 2e5 + 5;


int main()
{
	std::ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	int t;
	cin >> t;

	while (t--)
	{
		int n;
		cin >> n;

		if (n == 1)
        {
			cout << 1 << '\n';
			continue;
		}
		else if (n == 2)
        {
			cout << "1 2" << '\n';
			continue;
		}
		else if (n == 3)
        {
			cout << "2 1 3" << '\n';
			continue;
		}

		cout << 2 << " ";

		for (int i = 4; i <= (n + 3) / 2; i++)
			cout << i << " ";

		cout << 1 << " ";

		for (int i = (n + 3) / 2 + 1; i <= n; i++)
			cout << i << " ";

		cout << 3 << '\n';

	}

	return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值