内容
假设有根柱子,现要按下述规则在这根柱子中依次放入编号为的球
- 每次只能在某根柱子的最上面放球。
- 同一根柱子中,任何个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在根柱子上最多能放多少个球。例如,在根柱子上最多可放 个球。
对于给定的,计算在根柱子上最多能放多少个球。
出入
格式
输入
只有一行一个整数,代表柱子数。
输出
本题存在 Special Judge。
请将根柱子上最多能放的球数以及相应的放置方案输出。
输出的第一行是球数。
接下来的行,每行若干个整数,代表一根柱子上的球的编号,数字间用单个空格隔开。
样例
输入
4
1
输出
11
1 8
2 7 9
3 6 10
4 5 11
1
2
3
4
5
数据
范围
对于的数据,保证。
提示
网络流24题https://blog.csdn.net/weixin_43890363/article/details/131648120?spm=1001.2014.3001.5502
题解
每次放球可以放就放,如果都不行就新开一个柱子。
其正确性可以简述一下,虽然明白但是不太好解释:
第一,如果可以放一定放。如果此时的数字可以上却不放,另开一个新柱子,将来把放在上,也可以直接等效为放到,然后给开一个新柱子,因为最后得到最上面的数都是和。
第二,按照条件一来放,如果可以放,那么一定只有一个唯一的位置。可以尝试着自己放一放,会发现结果是一层一层的覆盖,小数会逐渐淹没,我们会依次凑而且当我们处于凑阶段的时候,我们待处理数字与顶部最小的数之和都,与最大数之和都,因此不存在两种可行方案。这是通过观察得到的,具体证明不太好说明,可以自己尝试不完全归纳法计算凑出所可以容纳的球,顶部的最小球最大球来证明。
#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;
}