求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

本文关键字:的对 有效      更新时间:2023-10-16

假设数组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可能会这样做:

  1. 创建一个哈希映射H,它包含集合 a a [j]的乘积。(如果你喜欢,你可以使用二维数组代替)。
  2. 设0初始化mK中的对数。然后,对于K的每个因子,求其在H中。如果存在,则将m增加1

运行时间: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;
}

查看演示