发现好像没人来证明贪心啊……那我来写一下它的证明
欲证明:放一个数在已有的柱上(如果可以)总是比新开一个柱更优的
假如已经放了x1..x2....xu..xv..xw....
现在我要放xx
我有两种策略
在xu
(xu
代表可以与xx
组成完全平方数的数)上放,或者新开一个柱子
即x1..x2....xx..xv..xw....
orx1..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;
}