使用 C++ 求和形式为 k^m, m >= 0 的子数组的数量
在本文中,我们将解释有关在C++中求解具有k^m,m>=0形式之和的子数组数量的所有内容。给定一个数组arr[]和一个整数K,我们需要找到具有K^m形式的总和的子数组的数量,其中m大于等于0,或者我们可以说我们需要找到具有sum等于K的某个非负幂。
Input: arr[] = { 2, 2, 2, 2 } K = 2 Output: 8 Sub-arrays with below indexes are valid: [1, 1], [2, 2], [3, 3], [4, 4], [1, 2], [2, 3], [3, 4], [1, 4] Input: arr[] = { 3, -6, -3, 12 } K = -3 Output: 3
想到的主要有两种方法-
蛮力
在这种方法中,我们将遍历所有子数组并检查它们是否是K的某个正整数幂;如果是,那么我们增加计数。
示例
#include <bits/stdc++.h> #define MAX 1000000 using namespace std; int main(){ int arr[] = {2, 2, 2, 2}; //给定数组 int k = 2; //给定整数 int n = sizeof(arr) / sizeof(arr[0]); //我们数组的大小 int answer = 0; //计数器变量 for(int i = 0; i < n; i++){ int sum = 0; for(int j = i; j < n; j++){ //这将循环将使所有子数组 sum += arr[j]; int b = 1; while(b < MAX && sum > b) //k^m最大值应该是10^6 b *= k; if(b == sum) //如果b==sum然后增加计数 answer++; } } cout << answer << "\n"; }输出结果
8
然而,这种方法不是很好,因为这个程序的时间复杂度是O(N*N*log(K)),其中N是我们数组的大小,K是用户给出的整数。
这种复杂度并不好,因为这种复杂度可以用于更高的约束,因为如果约束很大,则需要太多时间来处理,因此我们将尝试另一种方法,以便我们可以将程序用于更高的约束。
有效的方法
在这种方法中,我们将使用前缀和和映射来减少我们的处理,这将大大降低我们的时间复杂度。
示例
#include <bits/stdc++.h> #define ll long long #define MAX 1000000 using namespace std; int main(){ int arr[] = {2, 2, 2, 2}; //给定的数组 int n = sizeof(arr) / sizeof(arr[0]); //我们数组的大小 int k = 2; //给定整数 ll prefix_sum[MAX]; prefix_sum[0] = 0; partial_sum(arr, arr + n, prefix_sum + 1); //制作前缀和数组 ll sum; if (k == 1){ //我们将分别检查1 sum = 0; map<ll, int> m; for (int i = n; i >= 0; i--){ //如果m[a+b]=c,则将c添加到当前和。 if (m.find(prefix_sum[i] + 1) != m.end()) sum += m[prefix_sum[i] + 1]; //增加前缀和的计数。 m[prefix_sum[i]]++; } cout << sum << "\n"; } else if (k == -1){ //我们将分别检查-1 sum = 0; map<ll, int> m; for (int i = n; i >= 0; i--){ //如果m[a+b]=c,则将c添加到当前和。 if (m.find(prefix_sum[i] + 1) != m.end()) sum += m[prefix_sum[i] + 1]; if (m.find(prefix_sum[i] - 1) != m.end()) sum += m[prefix_sum[i] - 1]; //增加前缀和的计数。 m[prefix_sum[i]]++; } cout << sum << "\n"; } else{ sum = 0; ll b; map<ll, int> m; for (int i = n; i >= 0; i--){ b = 1; while (b < MAX){ //我们不会检查超过10^6 //如果m[a+b]=c,则将c添加到当前和。 if (m.find(prefix_sum[i] + b) != m.end()) sum += m[prefix_sum[i] + b]; b *= k; } m[prefix_sum[i]]++; } cout << sum << "\n"; } return 0; }输出结果
8
结论
我们解决了一个问题,以找到具有k^m形式的总和的子数组的数量,其中m>=0的时间复杂度为O(·nlog(k)log(n))。我们还学习了针对这个问题的C++程序以及我们解决这个问题的完整方法(普通和高效)。我们可以用其他语言编写相同的程序,例如C、java、python和其他语言。希望这篇文章对您有所帮助。