372. 超级次方
Posted Debroon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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. 超级次方的主要内容,如果未能解决你的问题,请参考以下文章