Codeforces Round 812 (Div. 2) C. Build Permutation

Codeforces 题解 - [Codeforces Round 812 (Div. 2)C. Build Permutation]

题目链接

题目描述

A \(\mathbf{0}\)-indexed array \(a\) of size \(n\) is called good if for all valid indices \(i\) (\(0 \le i \le n-1\)), \(a_i + i\) is a perfect square\(^\dagger\).

Given an integer \(n\). Find a permutation\(^\ddagger\) \(p\) of \([0,1,2,\ldots,n-1]\) that is good or determine that no such permutation exists.

\(^\dagger\) An integer \(x\) is said to be a perfect square if there exists an integer \(y\) such that \(x = y^2\).

\(^\ddagger\) An array \(b\) is a permutation of an array \(a\) if \(b\) consists of the elements of \(a\) in arbitrary order. For example, \([4,2,3,4]\) is a permutation of \([3,2,4,4]\) while \([1,2,2]\) is not a permutation of \([1,2,3]\).

输入格式

Input

The first line contains a single integer \(t\) (\(1 \le t \le 10^4\)) — the number of test cases.

The only line of each test case contains a single integer \(n\) (\(1 \le n \le 10^5\)) — the length of the permutation \(p\).

It is guaranteed that the sum of \(n\) over all test cases does not exceed \(10^5\).

输出格式

Output

For each test case, output \(n\) distinct integers \(p_0, p_1, \dots, p_{n-1}\) (\(0 \le p_i \le n-1\)) — the permutation \(p\) — if the answer exists, and \(-1\) otherwise.

题目大意

给定一个长度为n的数组,数组中的元素为\([0,1,2,\ldots,n-1]\),要求数组中每个元素加上其下标后为一个完全平方数。即\(a_i + i\)为一个完全平方数。

输入

3
3
4
7

输出

1 0 2 
0 3 2 1 
1 0 2 6 5 4 3 

解题思路

  • 所有情况均数组均存在

  • 在[n, 2n]中一定存在至少一个完全平方数\(n < \lceil \sqrt{n} \rceil ^2 \leq 2n\)

证明引用

易得

\[\lceil \sqrt{n} \rceil \leq \sqrt{n} + 1 \]

两边平方

\[\lceil \sqrt{n} \rceil^2 \leq n + 2\sqrt{n} + 1 \]

我们希望

\[n + 2\sqrt{n} + 1 \leq 2n \]

\[2\sqrt{n} + 1 \leq n \]

\[n - 2\sqrt{n} - 1 \leq 0 \]

\(\sqrt{n} = x, x \in [0, \infty].\)

\[x^2 - 2x - 1 \leq 0 \]

解得两根

\[x = \frac{2 \pm 2\sqrt{2}}{2} \]

\[x = 1\pm \sqrt{2} \]

\[\because x \in [0, \infty] \]

\[\therefore x = 1 + \sqrt{2} \]

\[\therefore x \geq 1 + \sqrt{2} \]

\[\therefore n \geq 3 + 2\sqrt{2} = 3 + 2\sqrt{2} \approx 5.828 \]

则当n大于等于6时,\(n + 2\sqrt{n} + 1 \leq 2n\)成立

\[\lceil \sqrt{n} \rceil ^2 \leq 2n \]

易知

\[n \leq \lceil \sqrt{n} \rceil ^2 \]

\[n < \lceil \sqrt{n} \rceil ^2 \leq 2n \]

得证

  • 递归
    设h为不超过k的最小平方数,因此 \(h \leq 2k\),也就是\(h - k \leq k\)
    因此我们可以用\(p_{i} = h - i\)来填充\((h - k \leq i \leq k)\).使用这种方法,我们可以递归地将k减少到h - k - 1. 然后一直减到 -1。

我们可以证明 \(h - k \geq 0\) 因为 \(h \geq k\)

代码实现

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

constexpr int Mxn = 1e5 + 10;

void Solution()
{
	int n;
	cin >> n;
	vector<int> a(n);
	function<void(int)> Recurse = [&](int r)
	{
		// cout << "r = " << r << '\n';
		if(r < 0) return;
		int h = sqrt(2 * r);
		h *= h;
		int l = h - r;
		Recurse(l - 1);
		for(;l <= r;++l, --r)
		{
			a[l] = r;
			a[r] = l;
		}
	};
	Recurse(n - 1);
	for(auto x : a) cout << x << ' '; cout << '\n';
	return;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	while(t--)
		Solution();
	return 0;
}
/*
1
1
2
3
4
5
6
7
8
9
10
*/
posted @ 2025-01-21 20:10  MatinalCosmos  阅读(40)  评论(0)    收藏  举报