poj 1289(求任意N次方根)

问题描述:

已知:存在一个满M叉树,该树任意结点的值是其父结点值的1/(M+1),叶节点的值为1。.已知根结点的值(记为H)和叶结点的个数(记为N)

求:非叶结点的个数和所有结点值之和


输入:若干case,每个case独立一行,包含两个整数分别代表根结点的值和叶结点的个数,0 0表示输入结束

输出:每组case对应的非叶结点的个数和所有结点值之和


Sample Input:

216 125

5764801 1679616

0 0


Sample Output:

31 671

335923 30275911


思路:

记给定树的深度为D(从0开始),根据问题描述易知如下特性:

  • M^D = N
  • (M+1)^D = H
因此,本题的唯一难点在于通过试任意N次方根求D和M。本题有两个陷阱:首先,采用试N次方的方法会导致TLE,因为对底数和指数都要试验,非常耗时;其次, 直接使用类似于pow(N, 1/D)所得结果存在误差,不能直接使用

代码:
#include <stdio.h>
#include <math.h>
int main(){
	unsigned long long h, n, ans1, ans2, m;  //n为叶结点个数,m为度
	int odd;
	double d, t1, t2;  //d表示深度
	while(1){
		scanf("%lld%lld", &h, &n);
		if(h == 0 && n == 0) break;
		else if(n == 1 && h == 1) printf("0 1\n");
		else{
			for(d = 1; d <= 32; d++){
				t1 = pow(h, 1.0/d);
				t2 = pow(n, 1.0/d);
				if(fabs(t1-t2-1)<1e-14)  //关键,使用pow()求任意N次方根存在误差,这里的1e-14即允许的误差范围
					break;
			}
			if(n != 1){
				m = t2+0.1;  //关键,开方的结果t2(浮点数)转换为整型,需要加一个小数0.1,而不能使用ceil()或floor()
				ans1 = (n-1)/(m-1);  //推导所得公式
				ans2 = num*(h-n)+h;
			}
			else{
				m = 1;
				ans1 = d;
				ans2 = 2*h-n;
			}
			printf("%lld %lld\n", ans1, ans2);
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值