魔术球问题

内容

假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3...的球

  • 每次只能在某根柱子的最上面放球。
  • 同一根柱子中,任何2个相邻球的编号之和为完全平方数。

试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4根柱子上最多可放 11个球。
对于给定的n,计算在n根柱子上最多能放多少个球。

出入

格式

输入

只有一行一个整数n,代表柱子数。

输出

本题存在 Special Judge。
请将n根柱子上最多能放的球数以及相应的放置方案输出。
输出的第一行是球数。
接下来的n行,每行若干个整数,代表一根柱子上的球的编号,数字间用单个空格隔开。

样例

输入

4
1

输出

11
1 8
2 7 9
3 6 10
4 5 11
1
2
3
4
5


数据

范围

对于100\%的数据,保证1 \leq n \leq 55

提示

网络流24题https://blog.csdn.net/weixin_43890363/article/details/131648120?spm=1001.2014.3001.5502

题解

每次放球可以放就放,如果都不行就新开一个柱子。
其正确性可以简述一下,虽然明白但是不太好解释:
第一,如果可以放一定放。如果此时的数字a可以b上却不放,另开一个新柱子,将来把c放在b上,也可以直接等效为放ab,然后给c开一个新柱子,因为最后得到最上面的数都是ac
第二,按照条件一来放,如果可以放,那么一定只有一个唯一的位置。可以尝试着自己放一放,会发现结果是一层一层的覆盖,小数会逐渐淹没,我们会依次凑3^2,4^2,5^2...而且当我们处于凑4^2阶段的时候,我们待处理数字与顶部最小的数之和都\geq3^2,与最大数之和都\leq5^2,因此不存在两种可行方案。这是通过观察得到的,具体证明不太好说明,可以自己尝试不完全归纳法计算凑出x^2所可以容纳的球,顶部的最小球最大球来证明。

#include<bits/locale_facets.h>
#include<math.h>
#include<stdio.h>
#include<queue>
inline void output(long long o);
inline long long input();
inline double sq(double x){return x*x;}
std::queue<short>pillar[56];
int main(){
	short n=input(),NUM=0;
	for(short i=1,j;;i++){
		for(j=1;j<=NUM;j++)
		if(sq((int)sqrt(pillar[j].back()+i))==pillar[j].back()+i){
			pillar[j].push(i);
			break;
		}if(j>NUM){
			if(++NUM>n){
				output(i-1),putchar('\n');
				for(j=1;j<=n;j++){
					for(;pillar[j].size()>1;pillar[j].pop())output(pillar[j].front()),putchar(' ');
					output(pillar[j].back()),putchar('\n');
				}return 0;
			}pillar[NUM].push(i);
		}
	}
}inline void output(long long o){
	if(o<0)putchar('-'),o=-o;
	if(o>=10)output(o/10);
	putchar(o%10^'0');
}inline long long input(){
	bool minus=false;
	char now=getchar();
	long long i=0;
	for(;!isdigit(now);now=getchar())
	if(now=='-')minus=!minus;
	for(;isdigit(now);now=getchar())i=(i<<3)+(i<<1)+(now^'0');
	return minus?-i:i;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值