HDU 5573 Binary Tree(2015-ICPC-上海赛区)
题目连接:题目
大意:
有一颗完全二叉树,第一个节点是1,他的左儿子就是i x 2,右儿子是i x 2+1
然后让你找到一个路径,使得通过加减恰好向下走k步之后,权值和为n,
解题思路:
构造题
首先我们可以分析得到,所有答案都可以通过走 1,2,4,8,16.....来得到
为什么?因为n<=2^k.
如果是奇数,那么我们最后一步就选左儿子,否则选择右儿子
路径问题解决了,我们就差符号问题了
符号问题,我们就可以通过找规律来解决
比如 n的二进制为100101
那么我们k步的符号就可以是110010(1表示+,0表示-)
就第一个位置是1,其他位置都是0就好了
比如001,你可以通过4-2-1来构造出来,就是001->100
--------------------
构造题好费脑
#include<cstdio> #include<iostream> #include<string> #include<cstring> using namespace std; long long n,k; int flag=0; int a[100+10]; int main(int argc, char const *argv[]) { int t;scanf("%d",&t); for(int p=1;p<=t;p++){ scanf("%lld%lld",&n,&k); flag=0; memset(a,0,sizeof(a)); if(n%2==0){ //构造奇数 flag=1; n=n-1; } int tmp=0; for(int i=k-1;i>=0;i--){ a[i]=1-tmp; tmp=1; if((n>>i)&1) { tmp=0; printf("%d %d\n",(n>>i)&1,i); } } printf("Case #%d:\n",p); long long now = 1; for(int i=0;i<k-1;i++){ printf("%lld ",now); now = now*2; if(a[i]) printf("+\n"); else printf("-\n"); } if(flag) printf("%lld ",now+1); else printf("%lld ",now); if(a[k-1]) printf("+\n"); else printf("-\n"); } return 0; }