Medium
题目描述
有一个有 n 个顶点的正凸多边形。顶点按顺时针方向从 0 到 n - 1 标记,每个顶点上恰好有一只猴子。下图展示了一个有 6 个顶点的凸多边形。
同时,每只猴子移动到相邻的顶点。如果移动后至少有两只猴子停留在同一个顶点上或在边上相交,就会发生碰撞。
返回猴子移动时至少发生一次碰撞的方法数。由于答案可能很大,返回对 10^9 + 7 取模的结果。
示例 1:
输入:n = 3
输出:6
解释:总共有 8 种可能的移动方式。
其中 2 种会发生碰撞的方式:
- 猴子 1 顺时针移动;猴子 2 逆时针移动;猴子 3 顺时针移动。猴子 1 和 2 发生碰撞。
- 猴子 1 逆时针移动;猴子 2 逆时针移动;猴子 3 顺时针移动。猴子 1 和 3 发生碰撞。
示例 2:
输入:n = 4
输出:14
约束条件:
3 <= n <= 10^9
提示:
- 尝试计算猴子不会碰撞的方法数。
解题思路
这是一道数学问题,关键是理解题目并找到规律。
思路分析:
每只猴子有两种移动选择:顺时针或逆时针移动到相邻顶点。因此总的移动方案数为 2^n。
题目要求的是"至少发生一次碰撞"的方案数,我们可以用补集思想:
- 总方案数 - 不发生碰撞的方案数 = 至少发生一次碰撞的方案数
什么情况下不会发生碰撞?
- 所有猴子都朝同一个方向移动(全部顺时针或全部逆时针)
- 这样每只猴子都会移动到下一个相邻位置,不会有两只猴子到达同一位置
因此不碰撞的方案数只有 2 种:
- 所有猴子都顺时针移动
- 所有猴子都逆时针移动
所以答案为:2^n - 2
实现要点:
- 由于
n可达10^9,需要使用快速幂算法计算2^n mod (10^9 + 7) - 注意处理模运算,确保结果非负
代码实现
class Solution {
public:
int monkeyMove(int n) {
const int MOD = 1e9 + 7;
// 快速幂计算 2^n mod MOD
long long base = 2;
long long exp = n;
long long result = 1;
while (exp > 0) {
if (exp % 2 == 1) {
result = (result * base) % MOD;
}
base = (base * base) % MOD;
exp /= 2;
}
// 总方案数 - 不碰撞方案数
return (result - 2 + MOD) % MOD;
}
};
class Solution:
def monkeyMove(self, n: int) -> int:
MOD = 10**9 + 7
# 使用Python内置的pow函数进行快速幂
total = pow(2, n, MOD)
# 总方案数 - 不碰撞方案数
return (total - 2) % MOD
public class Solution {
public int MonkeyMove(int n) {
const int MOD = 1000000007;
// 快速幂计算 2^n mod MOD
long baseNum = 2;
long exp = n;
long result = 1;
while (exp > 0) {
if (exp % 2 == 1) {
result = (result * baseNum) % MOD;
}
baseNum = (baseNum * baseNum) % MOD;
exp /= 2;
}
// 总方案数 - 不碰撞方案数
return (int)((result - 2 + MOD) % MOD);
}
}
/**
* @param {number} n
* @return {number}
*/
var monkeyMove = function(n) {
const MOD = 1000000007;
function modPow(base, exp, mod) {
let result = 1;
base = base % mod;
while (exp > 0) {
if (exp % 2 === 1) {
result = (result * base) % mod;
}
exp = Math.floor(exp / 2);
base = (base * base) % mod;
}
return result;
}
const totalWays = modPow(2, n, MOD);
const noCollisionWays = 2;
return (totalWays - noCollisionWays + MOD) % MOD;
};
复杂度分析
| 复杂度类型 | 值 |
|---|---|
| 时间复杂度 | O(log n) |
| 空间复杂度 | O(1) |
说明:
- 时间复杂度:快速幂算法的时间复杂度为 O(log n)
- 空间复杂度:只使用了常数个变量,空间复杂度为 O(1)
相关题目
- . Pow(x, n) (Medium)