原题链接
一. 题目描述
给你一个下标从 0 开始的二维数组 variables ,其中 variables[i] = [ai, bi, ci, mi],以及一个整数 target 。
如果满足以下公式,则下标 i 是 好下标:
0 <= i < variables.length
((aibi % 10)ci) % mi == target
返回一个由 好下标 组成的数组,顺序不限 。
示例 1:
输入:variables = [[2,3,3,10],[3,3,3,1],[6,1,1,4]], target = 2
输出:[0,2]
解释:对于 variables 数组中的每个下标 i :
1) 对于下标 0 ,variables[0] = [2,3,3,10] ,(23 % 10)3 % 10 = 2 。
2) 对于下标 1 ,variables[1] = [3,3,3,1] ,(33 % 10)3 % 1 = 0 。
3) 对于下标 2 ,variables[2] = [6,1,1,4] ,(61 % 10)1 % 4 = 2 。
因此,返回 [0,2] 作为答案。
示例 2:
输入:variables = [[39,3,1000,1000]], target = 17
输出:[]
解释:对于 variables 数组中的每个下标 i :
1) 对于下标 0 ,variables[0] = [39,3,1000,1000] ,(393 % 10)1000 % 1000 = 1 。
因此,返回 [] 作为答案。
提示:
1 <= variables.length <= 100
variables[i] == [ai, bi, ci, mi]
1 <= ai, bi, ci, mi <= 103
0 <= target <= 103
二. 解题思路
本题意思非常简单,就是通过幂运算和取模来计算结果和给定的 target 的值是否相同,这里我们运用到一个比较实用和高效的方法求解幂运算—快速幂:
快速幂就是通过将指数进行二进制分解,利用指数的二进制表示来逐步计算幂的结果。具体来说,快速幂算法的时间复杂度为O(log n),与传统的幂运算算法相比,其效率有了极大的提高。这种算法通过将指数b表示为二进制形式,并利用幂的运算法则(a^(m+n) = a^m * a^n)将a^b拆分成更小的幂的乘积。通过逐步计算这些小幂的值,最后将它们相乘,即可得到a^b的结果。快速幂算法不仅适用于普通的幂运算,还广泛应用于大数运算、模幂运算和优化算法等方面,特别是在处理大数和需要高效计算的情况下显得尤为重要。
这里我们举个例子(3^5 % 5 = 3):
图画的有点丑,不要在意哈哈哈,言归正传,我们将3 的5 次方通过二进制拆分之后可以看出,如果二进制中某一位为1,则代表该位可以进行乘法,那我们只需要对幂运算拆分成很多个小的幂运算计算即可,(b & 1) 意思就是判断指数的二进制下一位是不是1,如果是,则进行乘法运算并对mod取模,如果不是则继续对底数进行平方,然后让指数向右移动一位,即(b = b >> 1)。
这样计算可以大大的优化时间复杂度,对一些大数的计算有很大的优化。
话不多说!!上代码!!
三. 代码
class Solution {
public:
int qmi(int a, int b, int mod){
int res = 1;
while(b){
if(b & 1) res = res * a % mod;
a = a *a % mod;
b >>= 1;
}
return res;
}
vector<int> getGoodIndices(vector<vector<int>>& variables, int target) {
vector<int> res;
for(int i = 0; i < variables.size(); i++){
int temp = qmi(variables[i][0], variables[i][1], 10);
int temp2 = qmi(temp, variables[i][2], variables[i][3]);
if(temp2 == target){
res.push_back(i);
}
}
return res;
}
};
四. 总结
时间复杂度:O(N∗Log(M));
空间复杂度:O(1)。