专栏文章

题解:CF2071B Perfecto

CF2071B题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@miq3i6y3
此快照首次捕获于
2025/12/03 22:21
3 个月前
此快照最后确认于
2025/12/03 22:21
3 个月前
查看原文

简述题意

判断是否存在一个排列:
  • 长度为 nn
  • i(1in),kN+,a1+a2++aik2\forall i(1\le i\le n),k\in \text N^+,a_1+a_2+\cdots+a_i\ne k^2
存在则输出。

算法分析

很容易判断无解:如果 n(n+1)2\dfrac{n(n+1)}{2} 为完全平方数,那么无解。
接下来判断如何输出一个解。
首先 n106\sum n\le10^6 告诉我们这题是 O(n)O(n) 的。
所以先构造 ai=ia_i=i
很显然,当前不为一个正解。
我们发现,前 ii 个数包含 [1,i][1,i] 的所有数。
那么前 i1i-1 个数的和为 i(i1)2\dfrac{i(i-1)}{2}。如果这个数不为完全平方数,跳过;否则,交换 i1i-1ii
因为令 i(i1)2=k2\dfrac{i(i-1)}{2}=k^2,第 i1i-1 个数为 zz。那么新方案前 i1i-1 个数和为 k2+izk^2+i-z,如果 k2+iz=K2k^2+i-z=K^2,则有 K=k+1K=k+1(不然和会超过),即 iz=2k+1i-z=2k+1
显然 kk2i\sqrt 2i 级别的,不存在 iz2k+1i-z\ge 2k+1,那么 k2+izk^2+i-z 不为完全平方数。
这样我们就找到了一个方案使得有解。

代码实现

CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[114514*10],sum[114514*10];
signed main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int n;
		cin>>n;
		if((n+1)*n/2==(int)sqrt((n+1)*n/2)*(int)sqrt((n+1)*n/2)) cout<<"-1\n";
		else
		{
			for(int i=1;i<=n;i++) a[i]=i;
			for(int i=1;i<=n;i++)
			{
				sum[i]=sum[i-1]+a[i];
				if(sum[i]==(int)sqrt(sum[i])*(int)sqrt(sum[i])) swap(a[i],a[i+1]);
				sum[i]=sum[i-1]+a[i];
			}
			for(int i=1;i<=n;i++) cout<<a[i]<<' ';
			cout<<'\n';
		}
	}
	return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...