【题解】LuoGu7108:移花接木

本文讲解了如何通过递归和接木的概念,解决不同情况下的树形结构问题,涉及砍叶、接木、接点数量计算等步骤。详细分析了当a、b、h取不同值时的具体操作和答案形式。

原题传送门
可以一个一个部分分推下来,放到联赛T1也是可以的,用时不会超过40min

  • h = 0 : h=0: h=0:把根的儿子都砍掉,答案为 a a a

  • a = b : a=b: a=b:把第 h h h层的所有点的儿子都砍掉,答案为 a h + 1 a^{h+1} ah+1

  • a = 1 : a=1: a=1:引入接木的概念,每次拿下来的一棵子树就是原树(因为是无限延展的),对于这个部分
    在这里插入图片描述
    其实就是非最后一层的点都要接上 b − 1 b-1 b1
    最后一层的点都要砍掉儿子
    然后其实可以先砍掉,再接木上去,并成一步操作
    答案就是最后一层的叶子个数, b h b^h bh

  • b = 1 : b=1: b=1:直接把多的东西砍掉,每一层就一个点保留,所以每层砍掉 a − 1 a-1 a1个,最后一层砍掉 a a a个,答案是 h ( a − 1 ) + a h(a-1)+a h(a1)+a

  • a < b : a<b: a<b:需要接木,根据上面得到的结论,可以先砍掉,再接上。每次考虑接上的时候,都存在一个地方可以断掉。所以只要考虑哪些要砍掉就行了。
    考虑现在已经全部接好了,那么最后一层的所有叶子的所有儿子都要砍掉,所以答案是 a ∗ b h a*b^h abh

  • a > b : a>b: a>b:还是直接砍光,每个点都要砍掉 a − b a-b ab个,总共的节点数用等比数列求和求出,答案是 ( a − b ) ( b h − 1 ) b − 1 + a ∗ b h \frac{(a-b)(b^h-1)}{b-1}+a*b^h b1(ab)(bh1)+abh

Code:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const LL qy = 1000000007;

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

LL ksm(LL n, LL k){
	LL s = 1;
	for (; k; k >>= 1, n = n * n % qy)
		if (k & 1) s = s * n % qy;
	return s;
}

int main(){
	int Q = read();
	while (Q--){
		LL a = read(), b = read(), h = read();
		if (h == 0) printf("%lld\n", a % qy);
		else if (a == b) printf("%lld\n", ksm(a, h + 1));
		else if (a == 1) printf("%lld\n", ksm(b, h));
		else if (b == 1) printf("%lld\n", (h * a % qy + a - h + qy) % qy);
		else if (a < b) printf("%lld\n", a * ksm(b, h) % qy);
		else printf("%lld\n", ((a - b) * (ksm(b, h) - 1 + qy) % qy * ksm(b - 1, qy - 2) % qy + a * ksm(b, h) % qy) % qy);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值