题目描述
Chocola 和 Vanilla 都喜欢蛋糕。今天,一家蛋糕店的经理送给她们总共 2k+1 个蛋糕。这些蛋糕被平均分配,所以她们每人一开始都收到了 2k 个蛋糕。
然而,Chocola 和 Vanilla 现在想要重新分配蛋糕,使得 Chocola 最终有恰好 x 个蛋糕,Vanilla 拥有剩下的 2k+1−x 个蛋糕。
在每一步操作中,她们可以执行以下两种操作之一,且只能选择其中之一:
- Chocola 把自己的一半蛋糕给 Vanilla。只有当 Chocola 当前蛋糕数为偶数时,这个操作才允许。
- Vanilla 把自己的一半蛋糕给 Chocola。只有当 Vanilla 当前蛋糕数为偶数时,这个操作才允许。
你的任务是确定最少需要多少步才能达到目标分配方式,并输出任意一种能达到最少步数的操作序列。
可以保证,在给定的约束条件下,总有合法解,并且最少所需的步数不超过 120。
输入格式
每组测试数据包含多个测试用例。第一行包含一个整数 t(1≤t≤1000),表示测试用例的数量。
每个测试用例的第一行包含两个整数 k 和 x(1≤k≤60,1≤x≤2k+1−1)------每个人一开始都有 2k 个蛋糕,x 是 Chocola 重新分配后应拥有的蛋糕数。
输出格式
对于每个测试用例,输出一个整数 n(0≤n≤120),表示至少需要几步操作才能完成蛋糕的重新分配。
下一行输出 n 个整数 o1,o2,...,on(oi=1 或 oi=2),表示第 i 步执行的操作:oi=1 代表本步 Chocola 给 Vanilla 一半蛋糕(操作 1),oi=2 代表本步 Vanilla 给 Chocola 一半蛋糕(操作 2)。
输入输出样例
输入 #1复制
4
2 3
2 4
3 7
2 5
输出 #1复制
2
2 1
0
3
2 2 1
2
1 2
说明/提示
在第一个测试用例中,她们可以用以下步骤使得 Chocola 恰好有 x=3 个蛋糕,Vanilla 有 2k+1−x=5 个蛋糕。用 {a,b} 表示当前 Chocola 拥有 a 个蛋糕,Vanilla 拥有 b 个蛋糕。
{4,4}o1=2{6,2}o2=1{3,5}
在第二个测试用例中,Chocola 已有恰好 x=4 个蛋糕,Vanilla 已有 2k+1−x=4 个蛋糕,因此无需操作。
在第三个测试用例中,她们可以用以下步骤使得 Chocola 恰好有 x=7 个蛋糕,Vanilla 有 2k+1−x=9 个蛋糕。
{8,8}o1=2{12,4}o2=2{14,2}o3=1{7,9}
这个代码没什么好说的,主要是注意两个细节。
cpp
#include "bits/stdc++.h"
#define int long long
using namespace std;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
//这个记得注释掉
//freopen("../input.txt","r",stdin);
int t;
cin>>t;
while (t--)
{
int k,x;
cin>>k>>x;
vector<int>ans;
//k<=60,1必须是long long类型,保证1<<k在合法移位范围
int tar=1LL<<k;//2^k
int sum=1LL<<(k+1);//2^(k+1)
int a=x;
int b=sum-a;
while (a!=tar)
{
//cout<<"a="<<a<<" b="<<b<<"\n";
if (a<b)
{
a<<=1;//a*=2
b=sum-a;
ans.push_back(1);
}
else
{
b<<=1;
a=sum-b;
ans.push_back(2);
}
}
cout<<ans.size()<<"\n";
reverse(ans.begin(),ans.end());
for (auto e:ans)
cout<<e<<" ";
cout<<"\n";
}
return 0;
}