CF1712B

题意

构造一个 \(n\) 的排列 \(p\),使得 $ \sum\limits_{i=1}^n \operatorname{lcm}(i,p_i)$ 最大。

分析

首先要知道,\(\operatorname{lcm}\) 是求两数的最小公倍数。因此,我们把思考方向引向公约数与公倍数。先回顾一下这条等式,对于任意的正整数 \(m\)\(n\) 都有

\[\gcd(m,n) \times \operatorname{lcm}(m,n)=m \times n \]

移项得

\[\operatorname{lcm}(m,n)= \dfrac {m \times n}{\gcd(m,n)} \]

既然要使等式的左边尽可能大,那么右边的分母自然越小越好(最小为 \(1\))。存在一种情况,使得 \(\gcd(m,n)=1\),即我们常说的互质。回顾一下互质的定义:若 \(m\)\(n\) 为两个相邻的正整数,则有 \(\gcd(m,n)=1\)。因此我们就要使题目中的 \(i\)\(p_i\) 互质,使得分母变为 \(1\)(最小的数)。

那么这题做法就很显然了:设 \(i\) 为奇数,则 \(i+1\) 为偶数,令 \(p_i=i+1\)\(p_{i+1}=i\),则 \(\gcd(i,p_i)=1\)\(\gcd(i+1,p_{i+1})=1\),满足条件。特别地,当 \(n\) 为奇数时,我们直接令 \(p_1=1\),其余情况从 \(2\) 开始,也满足条件,避免了剩下一个数的情况。

代码见下:

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int n;
		cin>>n;
		if(n&1)
		{
			cout<<1<<' ';
			for(int i=2;i<=n;i++)
				if(i&1^1)//等价于 i%2==0
					cout<<i+1<<' ';
				else
					cout<<i-1<<' ';
		}
		else
		{
			for(int i=1;i<=n;i++)
				if(i&1)
					cout<<i+1<<' ';
				else
					cout<<i-1<<' ';
		}
		cout<<endl;
	}
	return 0;
}
posted @ 2024-01-20 17:45  liyilang2021  阅读(1)  评论(0编辑  收藏  举报