luogu2765 魔术球问题

发现好像没人来证明贪心啊……那我来写一下它的证明

欲证明:放一个数在已有的柱上(如果可以)总是比新开一个柱更优的

假如已经放了x1..x2....xu..xv..xw....
现在我要放xx

我有两种策略

xuxu代表可以与xx组成完全平方数的数)上放,或者新开一个柱子


x1..x2....xx..xv..xw....
or
x1..x2....xu..xv..xw....xx

然后再考虑xx+1

对于x1..x2......xv..xw....,上下两种都是一样的,就不说了

既然xu可以与xx组成完全平方数,则xu+xx=a*a
可以发现,xu+1+xx 不可以放在xu上面,(为什么呢?倘若可以,即xu+1+xx==b*b,即1=b*b-a*a,而b>a>=1……
那么,xx+1还不如放在xx上哩。

如果xx+1放在不是xx上的地方,则上面一种更优。因为倘若再来个什么xa,它大可以再开一个柱子。(有的同学可能发现这里的证明有点不完整,大概说一下,就是考虑xa放在xu上的所有柱子的形态和新开一个柱子的所有柱子的形态)。

代码很好写啦。(据说\(n\leq 60\)

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
int n, cnt, ans=1, isa[3205];
vector<int> d[62];
int main(){
	for(int i=1; i*i<=3205; i++)
		isa[i*i] = true;
	cin>>n;
	while(1){
		for(int i=1; i<=cnt; i++)
			if(isa[d[i][d[i].size()-1]+ans]){
				d[i].push_back(ans);
				ans++;
				i = 0;
				continue;
			}
		if(cnt<n)
			d[++cnt].push_back(ans++);
		else break;
	}
	cout<<ans-1<<endl;
	for(int i=1; i<=n; i++){
		for(int j=0; j<d[i].size(); j++)
			printf("%d ", d[i][j]);
		printf("\n");
	}
	return 0;
}
posted @ 2017-12-28 15:29  poorpool  阅读(138)  评论(0编辑  收藏  举报