C/C++教程

leetcode372——超级次方

本文主要是介绍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——超级次方的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!