NowCoder Wannafly 27E 黄魔法师 构造

原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-Wannafly27E.html

题目传送门 - NowCoder Wannafly 27E

题意

  给出 n, k,求一个长度为 n 的数组 a, 满足有恰好 k 对数对 (i, j) (1 <= i < j <= n) 满足 ai + aj 为完全平方数。如果不存在,输出 -1。

题解

  首先考虑最大能构造多少:

  容易发现,全部填 2 就是 n(n-1)/2 最大了。然后猜一猜小于等于这个的都是有解的。

  首先,找到满足 m(m-1)/2<=k 的最大 m , 则 k = 1+2+ … + m + x

  我们考虑构造这 m+1 个数来达到目的,假装其他的数不影响结果,设为 d 。

  于是可以想到一种构造方案:

  找到正整数 a,b,c,d ,满足:

    a+b,a+a,b+b,b+c 是完全平方数

    a+c,a+d,b+d,c+d,d+d,c+c 不是完全平方数。

  那么,我们考虑分 x = 0 和 x>0 讨论:

  如果 x = 0 ,那么直接放 m 个 a 然后其他的放 d 就好了。

  如果 x > 0 ,那么放 m-x 个 a,x 个 b,放一个 c ,剩下的放 d 即可。

  手造出这样的 abcd 比较麻烦,但是这样的 abcd 在 10w 范围内显然是很容易找的,直接写个代码暴搜即可。

  由于 我太懒了,直接用了 珂爷 的: a=98,b=2,c=7 。我 d 随便取了个 1 。

  话说 珂爷 太巨了,E 题一血虐场 Orz 。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005;
LL read(){
	LL x=0;
	char ch=getchar();
	while (!isdigit(ch))
		ch=getchar();
	while (isdigit(ch))
		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
LL n,k;
int a=98,b=2,c=7,d=1;
vector <int> v;
int main(){
	n=read(),k=read();
	if (n*(n-1)/2<k)
		return puts("-1"),0;
	if (!k){
		for (int i=1;i<=n;i++)
			printf("1 ");
		return 0;
	}
	v.clear();
	while ((n-1)*(n-2)/2>=k){
		v.push_back(d);
		n--;
	}
	if (n*(n-1)/2==k)
		for (int i=1;i<=n;i++)
			v.push_back(a);
	else {
		v.push_back(c);
		LL rem=k-(n-1)*(n-2)/2;
		for (int i=1;i<=rem;i++)
			v.push_back(b);
		for (int i=n-1-rem;i>=1;i--)
			v.push_back(a);
	}
	for (auto i : v)
		printf("%d ",i);
	return 0;
}

  

 

posted @ 2018-10-26 23:00  zzd233  阅读(390)  评论(2编辑  收藏  举报