[eJOI2019] 塔
[eJOI2019] 塔
题面
从序列中选择一段连续序列,将序列和加入序列,求最小操作次数生成
分析
初看感觉没什么思路。
1. 先考虑每次操作都选择整个序列
多次操作后序列为:
我们能发现
2. 试着对于某次操作不选择整个序列
随便选择一次操作,
这个序列只是将原序列中的
后面的操作还是选择整个序列。
我们发现,当
换句话说,当
那么我们是不是可以只令
所以我们对于任意一次操作,只用考虑从
3. 实现
例如:
我们要得到
让
等同于让
所以从
所以我们先让每次操作都选择整个序列,对于要得到的数
4. 代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,n,m,now,t,ans[70];
signed main()
{
// freopen("tower.in","r",stdin);
// freopen("tower.out","w",stdout);
scanf("%lld",&T);
while(T--)
{
scanf("%lld",&n);m=1;
if(n==1){puts("0");continue;}
t=1;ans[1]=1;
while(m<n)
{
t++;
ans[t]=1;
m<<=1;
}
n=m-n;
now=t-1;
printf("%d\n",t);
while(n)
{
if(n&1)ans[now]=2;
now--;
n>>=1;
}
for(int i=1;i<=t;i++)printf("%d %d\n",ans[i],i);
}
}