数学题,高度 (infty) 是为了防止你想多考虑嫁接是否够用。
分析:
- ( ext{case1}):当 (age b) 时,只需要砍树就行,嫁接没有任何用处。
第 (0) 层要砍掉 ((a-b) o(a-b) imes b^0) 个树枝;
第 (1) 层要砍掉 ((a-b) imes b^1) 个树枝;
第 (2) 层要砍掉 ((a-b) imes b^2) 个树枝;
(cdots)
第 (h-1) 层要砍掉 ((a-b) imes b^{h-1}) 个树枝;
第 (h) 层要全部砍光,也就是 (a imes b^h) 个树枝。
所以一共砍掉了:
[(a-b) imesleft(b^0+b^1+b^2+cdots+b^{h-1}
ight)+a imes b^h
]
[=(a-b) imes frac{1-b^h}{1-b}+a imes b^h
]
用快速幂 (+) 逆元直接求就行。
注意 (b=1) 时的特判。
- ( ext{case2}):当 (a<b) 时,先用嫁接把 (h) 层以下的枝补全了,再考虑把 (h) 层砍光。
换的时候可以贪心,用第 (h) 层的树枝嫁接给之前的。
第 (0) 层要接 ((b-a) o (b-a) imes b^0) 个树枝;
第 (1) 层由于上一层新添了 (b-a) 个树枝,所以要接 ((b-a) imes b^1) 个树枝;
(cdots)
第 (h-1) 层就要接 ((b-a) imes b^{h-1}) 个树枝。
所以一共只需要 (a imes b^h) 次操作。
快速幂直接算。
时间复杂度是 (mathcal O(T imes log(h)))。
代码:
#include "cstdio"
#include "cctype"
#include "algorithm"
#define mod 1000000007
#define ll long long
ll ans, t, a, b, h;
char buffer[1 << 28], *S = buffer, puffer[1 << 28], *T = puffer;
inline ll read() {
int x(0), f(0);
while (!isdigit(*S))
f |= (*S++ == '-');
while (isdigit(*S))
x = (x << 1) + (x << 3) + (*S++ ^ 48);
return f ? -x : x;
}
inline void write(ll x) {
int num[28], sp = 0;
if (x < 0)
*T++ = '-', x = -x;
if (!x)
*T++ = 48;
while (x)
num[++sp] = x % 10, x /= 10;
while (sp)
*T++ = num[sp--] + 48;
}
inline ll power(ll x, ll y) {
ll res = 1;
while (y) {
if (y & 1)
res = res * x % mod;
x = x * x % mod;
y >>= 1;
}
return res;
}
inline ll pomod(ll x) {
return power(x, mod - 2);
}
int main() {
fread(buffer, 1, 1 << 28, stdin);
t = read();
while (t--) {
a = read(), b = read(), h = read();
int k = power(b, h);
if (a > b) {
if (b == 1)
write(((a - b)*h % mod + a * k % mod) % mod);
else
write(((a - b) * (k - 1) % mod * pomod(b - 1) % mod + a * k % mod) % mod);
} else
write(a * k % mod);
*T++ = '
';
}
fwrite(puffer, 1, T - puffer, stdout);
return 0;
}