leetcode372——超级次方
Posted Aline2021-yxz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode372——超级次方相关的知识,希望对你有一定的参考价值。
题目链接:超级次方
只是看到题目,还没看内容就觉得是要用快速幂来玩,但是做完后感觉还是遍历简单
使用mod的性质:(a*b)%c=( a % c * b % c ) % c 来解决溢出
class Solution
public:
//计算c的seconary次方
int pow1(int c, int secondary)
int res = 1;
while (secondary)
res = ((res%1337)*(c%1337)) % 1337;
//上述写法与res=(res*c)%1337一样,但
//比较好理解为什么不会溢出
secondary--;
return res;
int superPow(int a, vector<int>& b)
int res = 1;
auto it = b.rbegin();
//将问题分开:每次只算一个位置的次方,
//最后乘起来就好了
while (it != b.rend())//计算结果
res = (res%1337*pow1(a, *it)%1337) % 1337;
a = pow1(a, 10);//计算下一个次方的底数
it++;
return res;
;
代码比较朴实无华,pow1函数算的就是一个数的n次方,
这个解法妙的地方的是 a = pow1(a, 10); 这一行代码
对于
a:2
b:[1,1]
这个测试用例来说,我们的思路一般会是这样:
res=22222222222
但使用上面的算法是:
res=2 * (2 ^ 10) ^ 1
两者的区别在哪呢?
对于第一种算法,我们在b的1下标位置很明显知道是2的一次方,但是来到0下标的时候还是1次方吗?不是,是1*10^1=10,那机器要知道是几次方不就需要知道这是第几位,还需要保存一下次方嘛,那对于很大的数组就会有一个严峻的问题:没有足够大的类型保存次方。
那么第二种算法的思路:我不算你次方是多大,我算你底数是多大,因为数组每间隔一位,次方位数之间就相差1,我们可以思考利用一下这个性质:
2
[3,4,5,6]
第一次:2^ (1 * 6) == (21)^6
第二次:2^(10 * 5) == (210)^5
第三次:2^(10 * 10 * 4) == (2100)^4
第四次:2^(10 * 10 * 10 * 3) == (21000)^3
可以发现底数每次都以相同的规律增大,都变为上一次的10次方,因为我们写的pow1函数算的正好是求某一个数的n次方,在里面已经解决了溢出问题,所以 a = pow1(a, 10);这行代码就很容易理解了
对于溢出问题,因为mod的性质让我们可以对任何一个参与*的数字都取mod,所以我们可以在 *运算中对所有数都取mod,当然如果不想只需要在可能溢出的位置取mod即可!
感觉挺好玩的,就写了些和大家一起分享✨
以上是关于leetcode372——超级次方的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 383. 赎金信 / 372. 超级次方 / 1816. 截断句子