HDU 5573 题解

题意:关于一只要续命的青蛙(雾),一颗完全二叉树,它的标号正如我们所期望的根为1,左儿子为父节点*2,右儿子为父节点*2+1,然后老青蛙从根往下走,一共走K步,它需要n个灵魂,每走过一个点,可以减去或加上这个点的标号,输出一种可能方案,输入数据保证至少有一组解

1=<n<=1e9,N<=2k<=260

共1~100组数据,1000MS

题解/思路:其实这道题找一下规律就好了,你会发现最左边两条路径分别可以表示±1,±3,……,±(2k-1)和±2,±4,……,±2k,所以只需判断这两条边哪条满足就好了(事实上分奇偶就好),至于输出方案,就从第k深度开始往上走,令now=n,每次走过一个点,若now>0,则加上这个点,若now<=0,则减去这个点(因为每个点标号比他的父辈的和还大,唯有这样才可能满足条件)。

也可以用二进制方法进行构造(仍从k深度往上走),注意到0001=1000-0100-0010-0001,能发现最左边两条边就能构造出符合题意的解:把N转化成二进制,最后一位为0则从最左边节点出发,最后一位为1则从最左边节点的右边一个节点出发。若一个 1前面有零,则这个点选择-,前面的点也都选择-,直到下一个1再进行判断;若1前面为1,则选择+;重复该操作即可。

#include<iostream>
#include<cstring>
using namespace std;
int t,n,k,sb,tot;
int v[100][2];

bool ok(int dx,int now){
    if (now==1) if (dx==1 || dx==-1) {v[++tot][1]=dx==1?1:2;v[tot][0]=now;return true;}else return false;
    if (dx>0) {v[++tot][1]=1;v[tot][0]=now;return ok(dx-now,now/2);}else {v[++tot][1]=2;v[tot][0]=now;return ok(dx+now,now/2);}
}

int main()
{
    cin>>t;
    for (int q=1;q<=t;++q){
        cin>>n>>k;
        //memset(v,0,sizeof(v));
        sb=1<<(k-1);
        tot=0;
        if (!ok(n,sb)){
            tot=0;
            ok(n,sb+1);
        }
        cout<<"Case #"<<q<<":"<<endl;
        for (int i=tot;i>=1;--i)
            if (v[i][1]==1) cout<<v[i][0]<<" +"<<endl;
                else if (v[i][1]==2) cout<<v[i][0]<<" -"<<endl;
    }
}
时间: 2024-10-23 03:35:48

HDU 5573 题解的相关文章

HDU 5573 Binary Tree(找规律)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5573 题意:给你一个完全二叉树,节点为自然数的排列(第一行1,第二行2 3,第三行4 5 6 7...).现在,给你一个N和K,K表示给你这个完全二叉树的前K行,从第1行到第K行有很多路径,希望找到一条路径能表示N,路径上的节点可取正也可取负,要求最后的和为N. 思路:由题目给的数据范围可知前两个节点有一个一定可以表示N.(前两个节点可以表示1 - 2^k) code: 1 #include <cs

【规律】【贪心】【数学】HDU 5573 Binary Tree

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5573 题目大意: 从1走到第k层,下一层的数是上一层的数*2或者*2+1,可以选择加上或者减去走的数,最终要求结果为n 输出每层走的数,和是加还是减 题目思路: [规律][贪心][数学] 首先苦思冥想一下,发现,1 2 4 8...2k可以凑成任意的奇数.而偶数只需要把2k变为2k+1. (从k往1位考虑加减,把+看为1,-看为0,则1+2+4+...=2k-1,符号可以用二进制数X表示,为111

hdu - 1237 题解

题意:给出一个数字计算式,包含+,-,*,/四种符号,计算值 题解:最大坑点:不能仅仅判断第一个是0就结束计算,有可能有:0 + 1这样的情况 所以1.判断第一个是否是0,如果是,则判断下一个符号是否是'\n' 2.读入数字和运算符,如果是*,/,取出栈顶元素直接计算完成后压栈,如果是-,将数字相反数压栈,如果是+,将数字压栈. 3.计算栈内元素之和 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm>

2014年北京网络赛 Instrusive HDU 5040 题解 优先队列

网赛的时候看了这道题,发现就是平常的那种基础搜索题. 由于加了一个特殊条件:可以一次消耗3秒或原地停留1秒. 那就不能使用简单的队列了,需要使用优先队列才行. 题意 告诉一副地图:一个起点,一个终点,若干墙,若干监视器,剩下的是空地. 起点,终点,监视器都算空地. 监视器初始值会指定一个方向,共有四个方向. 监视器每秒顺时针转动到下个方向. 监视器视野距离为2. 在监视器的位置或在监视器面向的格子是监视区域. 普通的移动一格需要消耗1秒时间. 在监视器下移动一格需要消耗3秒时间. 如果呆在原地不

hdu - 1231 题解

题意:最大连续子序列问题+输出答案所在的区间 题解:最大连续子序列问题状态转移方程:f[i]=max(a[i],f[i-1]+a[i]) 答案所在区间的话可以在递推求状态的时候,顺便记录一下当前位置所在的序列左端点是谁,最后扫描的时候记录下最优解的位置,然后这个位置就是右端点,记录过的数据就是左端点. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring&g

hdu 5418 题解

第一眼看到这题,哇,这不是我刚做完的题吗?大水题!然后 这题表面很水,实际上有点坑. 题意 求经过 $ 1 - n $(不能遗漏) 并且回到 $ 1 $ 的最短路. 在看这题之前我们可以来看下这题 最短Hamilton路 这道题的要求是我们要让每个点不重不漏的经过并且最终到达 $ n-1 $ 我们看数据范围,就可以直接状压dp,枚举状态. 由于题目已经给出最短路,便可以直接计算 #include<bits/stdc++.h> using namespace std; int n,a[30][3

HDU 5521 题解

题意:给出n个点,John需要和一个住在第n个点的人在某个点碰面,再给出m个集合,每个集合中包含Si个点,这些点两两之间可以以ti时间互达,求两人需花费的最小时间,若无法走到第n个点,则输出Evil John. 2<=N<=100000;1<=ti<=1e9;Si>0;∑Si<=1e6; 共1~6组数据,6000MS 算法/思路: 第一次见到这种套路的话还是蛮有趣的,对每个集合中两两点建边显然会被轻松TLE. 使用最短路+虚拟节点:于是我们对每个集合建立一个虚拟节点,在

hdu 5573 Binary Tree 构造

Binary Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 774    Accepted Submission(s): 450Special Judge Problem Description The Old Frog King lives on the root of an infinite tree. According

HDU 5512 题解

题意:给出n,再给出集合A中的两个整数j,k且j≠k,集合满足条件 若j,k∈A,j≠k,且1<=j-k<=n,则j-k∈A: 若j,k∈A,j≠k,且1<=j+k<=n,则j+k∈A: 若集合A中有偶数个数,则输出Iaka:若集合A中有奇数个数,则输出Yuwgna. 2<=N<=20000.共1~500组数据,1000MS 算法/思路:由于减法的存在,可由辗转相除法知道gcd(i,j)在集合中,进而至少有2*gcd(i,j)在集合中,借此可以得知gcd(i,j)的n以