题意:给定N和K,K是二叉树的层次,N是要做出的值。
从1开始走堆式二叉树,每次必须加或者减当前值,必须跑完K层。
要求找一条路可以经过K层得到N的数值。
思路:
尝试1、2、4、8 发现可以得出±1,±3,±5,±7,±9,±11,±13,±15。
尝试1、2、4、9发现可以得出±2,±4,±6,±8,±10,±12,±14,±16。
发现可以使用k层内,20、21、22、... ... 2k-1或者2k-1+1 得出 [1,2k] 内的所有数。
并且可以唯一确定关系,如
15=8+4+2+1,16=9+4+2+1
13=8+4+2-1,14=9+4+2-1
11=8+4-2+1,12=9+4-2+1
...
7=8-4+2+1,8=9-4+2+1
5=8-4+2-1,6=9-4+2-1
3=8-4-2+1,4=9-4-2+1
1=8-4-2-1,2=9-4-2-1
取数方式为:设定值0,若当前值小于N则加上当前节点值,若当前值大于N则减去当前节点值
综上,又因为限制条件 1≤N≤2k 在k层的表示范围 [1,2k] 内,
所以,可以通过2k 2k+1 这两个叶子节点向上取数,若N为奇则从2k 开始,若N为偶则2k+1 开始。
因为已知取数方式唯一确定,所以构造结束。

#include<bits/stdc++.h> #define inf 0x3f3f3f3f #define MAX 1000001 #define inf 0x3f3f3f3f #define ll long long #define MAX 1000001 const ll N = 2e5+7; const ll mod = 1e9+7; using namespace std; ll n,k; void dfs(ll u,ll c,ll sum){//当前节点 当前层 当前值 if(c==0){ return ; } if(sum>n) dfs(u/2,c-1,sum-u); else dfs(u/2,c-1,sum+u); if(sum>n) printf("%lld - ",u); else printf("%lld + ",u); } int main(){ int t;scanf("%d",&t); for (int cas=1;cas<=t;cas++){ scanf("%lld%lld",&n,&k); printf("Case #%d: ",cas); int i=1<<(k-1); if(n%2==0) i++; dfs(i,k,0); } return 0; }