求A[i]和A[j]的乘积能有效除K的对i和j的个数
Find the number of pairs i and j such that the product of A[i] and A[j] divides K efficiently
假设数组a中有一个整数列表
给定另一个包含查询的数组Q。
对于每一个查询K,你需要找到i和j对的个数,使得A[i]和A[j]的乘积能整除K
如何在没有任何暴力方法的情况下有效地完成这一点?
例如:
在
A: 2 5 6 2 3
输出:5 0 2 3
说明:
能除12的对的个数为:(1,3),(1,4),(1,5),(3,4),(4,5)
能除7的对的个数为:None(0),以此类推…
如何在没有任何暴力方法的情况下有效地完成这一点?
质因数分解为质数的幂。
对于每个查询值,构建N维数组,其中N为查询值的素数因子。每个维度有k+1个元素,其中k是相应素数的幂。
绘制该数组中的每个潜在因子,将其位置加1。
使用n维扫描在每个维度上沿每个维度存储cdf。总共不到40个条目,所以这应该足够快了。
对每个潜在因子的"逆"位置求和。如果I_j和I_j无效,则通过将质数幂加倍并减去1来手动检查。
你可以预先考虑每个目标或每个源,并构建一个巨大的阵列。
就像这样快速拍摄:
你可以"预编译"一个包含所有可能的A[i] * A[j]
结果的列表S
,并过滤该列表中的双精度;
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
A可能会这样做:
- 创建一个哈希映射H,它包含集合 a 和 a [j]的乘积。(如果你喜欢,你可以使用二维数组代替)。
- 设0初始化m为K中的对数。然后,对于K的每个因子,求其在H中。如果存在,则将m增加
1
。
在c++:运行时间:
O(N * N) + c * Q
。其中N为数组A的大小;c为查询值的平均因子数;Q
为查询数。
#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;
}
查看演示
相关文章:
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 从C++中的对列表中访问特定元素
- 在C++中初始化向量映射的最有效方法
- 有没有办法在 c++ 中按更大的 int 和更小的对对 int 和对的集合进行排序?
- 对对应于矩阵的行和列的对向量进行排序
- 将此布尔值传递给此函数的最有效方法是什么?
- 在 capnp FlatArrayMessageReader 的对齐内存缓冲区中接收 zmq 消息
- 调整大小后保持对矢量元素的引用有效
- 在 stl 中使用向量和对的最有效实现 Dijkstra 最短路径C++
- CIN >> 在较大的数字下失败,但对较小的数字有效?
- 对向量中的一个元素进行排序的最有效方法
- 从一组有序对 (x, y) 中找到最长链的最有效算法是什么
- 使用 GCC 对大型位向量进行洗牌的最有效方法是什么
- 为什么返回对自动变量的引用有效
- 在STL列表中存储的每个项中存储对容器对象的引用的最有效方法
- 在有效地计算数组中第二个元素较少的对时,我哪里错了
- 在文件中存储由分隔符分隔的大量整数的键值对的最有效方法
- 如何处理pam_authenticate对有效用户和密码的PAM_AUTHTOK_RECOVERY_ERR返回值
- 从字符[]访问对齐的T和的最有效方法是什么?
- 求A[i]和A[j]的乘积能有效除K的对i和j的个数