本文主要是介绍372. 超级次方,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
372. 超级次方
- 题目
- 算法设计:迭代
- 算法设计:递归
题目
传送门:https://leetcode.cn/problems/super-pow/
题目不难懂,问题在于 b
是一个非常非常大的数,会溢出。
- 迭代和递归,各有解决方法,记录在下文。
算法设计:迭代
防止溢出,迭代拆解幂。
a 1564 a^{1564} a1564
= a 4 ∗ a 60 ∗ a 500 ∗ a 1000 a^{4}*a^{60}*a^{500}*a^{1000} a4∗a60∗a500∗a1000
= a 4 ∗ ( a 10 ) 6 ∗ ( a 100 ) 5 ∗ ( a 1000 ) 1 a^{4} * (a^{10})^6 * (a^{100})^5 * (a^{1000})^1 a4∗(a10)6∗(a100)5∗(a1000)1
int ans = 1;
for (int i = b.size() - 1; i >= 0; i--) { // 拆分幂ans = (ans * pow(a, b[i])) % k; // a^1564 = a^4 * (a^10)^6 * (a^100)^5 * (a^1000)^1,% k 防止溢出 a = pow(a, 10); // a^10、a^100、a^1000、a^1000(不会代入计算)
}
快速幂:比普通求幂算法要快
int quick_pow(int a, int b) { // 快速幂log(N),普通幂O(N)if( b == 0 ) return 1;if( b % 2 != 0 ) // k 是奇数return ( a % k * quick_pow( a, b-1 ) ) % k;else { // k 是偶数int sub = quick_pow( a, b/2 );return ( sub * sub ) % k;}
}
此外,模运算防止溢出:
- 正常模运算:(a × b) % k
- 防溢出模运算:(a % k) * (b % k) % k
class Solution {const int k = 1337;int pow(int a, int b) { // 快速幂log(N),普通幂O(N)if( b == 0 ) return 1;if( b % 2 ) // k 是奇数return ( a % k * pow( a, b-1 ) ) % k;else { // k 是偶数int sub = pow( a, b/2 );return ( sub * sub ) % k;}}
public:int superPow(int a, vector<int> &b) {int ans = 1;for (int i = b.size() - 1; i >= 0; i--) { // 拆分幂ans = (ans * pow(a, b[i])) % k; // a^1564 = a^4 + (a^10)^6 + (a^100)^5 + (a^1000)^1,% k 防止溢出 a = pow(a, 10); // a^10、a^100、a^1000、a^1000(不会代入计算)}return ans;}
};
算法设计:递归
防止溢出,递归拆分幂,分成俩部分:
- 数组末尾 * (数组剩余部分)^10
a 1564 a^{1564} a1564
= a 4 ∗ a 1560 a^{4}*a^{1560} a4∗a1560
= a 4 ∗ ( a 156 ) 10 a^{4}*(a^{156})^{10} a4∗(a156)10
= a 4 ∗ ( a 6 ∗ ( a 15 ) 10 ) 10 a^{4}*(a^{6}*(a^{15})^{10})^{10} a4∗(a6∗(a15)10)10
= a 4 ∗ ( a 6 ∗ ( a 5 ∗ a 10 ) 10 ) 10 ) 10 a^{4}*(a^{6}*(a^{5}*a^{10})^{10})^{10})^{10} a4∗(a6∗(a5∗a10)10)10)10
int next_pow( int a, int i, vector<int>& b ) { // 递归拆分幂,防止溢出if( i == -1 ) return 1;return ( quick_pow( a, b[i] ) * quick_pow( next_pow( a, i-1, b ), 10 ) ) % k;// 递归拆分幂,分成俩部分:数组末尾 * 数组剩余^10,再合并出俩者的结果
}
此外,模运算防止溢出:
- 正常模运算:(a × b) % k
- 防溢出模运算:(a % k) * (b % k) % k
完整代码:
class Solution {int k = 1337;
public:int quick_pow(int a, int b) { // 快速幂log(N),普通幂O(N)if( b == 0 ) return 1;if( b % 2 != 0 ) // k 是奇数return ( a % k * quick_pow( a, b-1 ) ) % k;else { // k 是偶数int sub = quick_pow( a, b/2 );return ( sub * sub ) % k;}}int next_pow( int a, int i, vector<int>& b ) { // 递归拆分幂,防止溢出if( i == -1 ) return 1;return ( quick_pow( a, b[i] ) * quick_pow( next_pow( a, i-1, b ), 10 ) ) % k;// 递归拆分幂,分成俩部分:数组末尾 * 数组剩余^10,再合并出俩者的结果 }int superPow(int a, vector<int>& b) {return next_pow( a, b.size()-1, b ); // 从最后一位开始}
};
这篇关于372. 超级次方的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!