假设数组A中有整数列表。
给定另一个包含查询的数组Q.
对于每个查询K,您需要找到对i和j的对数,使得A [i]和A [j]的乘积除以K.
如何在没有任何强力方法的情况下有效地完成这项工作?
例如:
鉴于
答:2 5 6 2 3
问:12 7 100 200
输出:5 0 2 3
说明:
除以12的对的数量为:(1,3),(1,4),(1,5),(3,4),(4,5)
除以7的对数:无(0)等......
如何在没有任何强力方法的情况下有效地完成这项工作?
答案 0 :(得分:2)
将所有因素归结为素数的幂。
对于每个查询值,构建N维数组,其中N是查询值的主要因子。每个维度都有k + 1个条目,其中k是相应素数的幂。
绘制此数组中的每个潜在因子,将其位置递增1.如果在数组外部,则丢弃。
使用n维扫描将cdf存储在每个维度的每个维度中。总共不到40个条目,所以这应该足够快。
每个潜在因素的“反向”位置。如果I_j和I_j无效,请通过加倍素数手动检查它并减去一次。
您可以预先计算每个目标或每个源,并构建一个巨大的阵列。但那可能太过分了。
答案 1 :(得分:0)
这样的快速拍摄:
您可以»预编译«所有可能S
结果的列表A[i] * A[j]
,并过滤该列表中的双重内容;
A = [1,2,3];
Q = [3,4,5]
All possible results:
1 * [2,3] => 2,3
2 * [1,3] => 2,6
3 * [1,2] => 3,6 //these are 6 values to test for each
S = [2,3,6] //here are only three unique
Than:
2/2, 2/3, 2/6 => 1
3/2, 3/3, 3/6 => 1
6/2, 6/3, 6/6 => 3
答案 2 :(得分:0)
A可能会这样做:
1
增加 m 。 运行时间:
O(N * N) + c * Q
。其中 N 是数组 A 的大小; c 是查询值的平均因子数;Q
是查询次数。
在C ++中:
#include <cmath>
#include <vector>
#include <iostream>
#include <unordered_map>
//returns a hashmap, containing all allowed pairs in vec
std::unordered_map<int, int> build_lookup_table(const std::vector<int>& vec){
std::unordered_map<int, int> table(vec.size());
for(std::size_t row = 0; row < vec.size(); row++)
for(std::size_t col = row + 1; col < vec.size(); col++)
++table[vec[row] * vec[col]];
return table;
}
//a fairly fast and simple way to quickly get factors without using % modulus
std::vector<int> get_factors(const int k){
std::vector<int> vec;
const int limit = std::sqrt(k);
for(int i = 1; i <= limit; i++){
int val = k / i;
if(val * i == k)
vec.push_back(i), vec.push_back(val);
}
if(limit * limit == k) //if its a perfect square
vec.pop_back();
return vec;
}
int main(){
std::vector<int> A{ 2, 5, 6, 2, 3 };
std::vector<int> Q{12, 20, 7, 10, 200 };
std::vector<int> ans(Q.size());
const auto lookup_table = build_lookup_table(A);
for(auto k : Q){
auto pairs = 0;
for(auto factor : get_factors(k)){
auto iter = lookup_table.find(factor);
pairs += iter != lookup_table.end() ? iter->second : 0;
}
ans.push_back(pairs);
}
for(auto x : ans)
std::cout << x << ' ';
std::cout << std::endl;
}