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;
}

转载于:https://www.cnblogs.com/poorpool/p/8135953.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值