现需要将一根长为正整数 bamboo_len 的竹子砍为若干段(至少两段),每段长度均为 正整数。请返回每段竹子长度的 最大乘积 是多少。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
**输入:**bamboo_len = 12
**输出:**81
提示:
2 <= bamboo_len <= 1000
通过数学推导(算术几何平均值不等式),将一个正数拆分成若干相等部分时,每部分越接近自然常数
乘积最大。在正整数中,最接近 e 的是 3,其次是 2。
使用贪心算法,由于我们要尽可能多地用 3,剩下的部分会有三种情况:
余数为 0:刚好全部分成 3,乘积为
余数为 1:最后剩下 3 * 1 ,这不如把一个 3 匀出来,变成 2 * 2 。乘积为 3^{k-1} * 4。
余数为 2:最后剩下一个 2,直接乘上去。乘积为 3^{k} * 2。
快速幂:
1 2 3 4 5 6 7 8 9 10 11 12
| long long qremainder(long long x, long long a, long long MOD) { long long rem = 1; while (a > 0) { if (a % 2 == 1) { rem = (rem * x) % MOD; } x = (x * x) % MOD; a /= 2; } return rem; }
|
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { public : int cuttingBamboo(int bamboo_len) { if (bamboo_len == 2 || bamboo_len == 3) return bamboo_len - 1;
long long MOD = 1000000007; long long a = bamboo_len / 3; long long b = bamboo_len % 3; long long rem; switch (b) { case 0: return qremainder(3, a, MOD); case 1: return (qremainder(3, a - 1, MOD) * (long long)4) % MOD; case 2: return (qremainder(3, a, MOD) * (long long)2) % MOD; } return -1; } long long qremainder(long long x, long long a, long long MOD) { long long rem = 1; while (a > 0) { if (a % 2 == 1) { rem = (rem * x) % MOD; } x = (x * x) % MOD; a /= 2; } return rem; } };
|