【问题标题】:Find the number of pairs i and j such that the product of A[i] and A[j] divides K efficiently求出 i 和 j 对的数量,使得 A[i] 和 A[j] 的乘积可以有效地整除 K
【发布时间】:2016-10-19 11:00:29
【问题描述】:

假设数组 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) 等等……

如何在没有暴力破解的情况下有效地做到这一点?

【问题讨论】:

  • 您尝试了什么,出了什么问题?你试过保理吗?数字和列表有多大?简单地打印出对的列表是 O(n^2)。多快才够快?
  • 链接到原始问题:codechef.com/NPLQ1601/problems/NPLELD我知道了
  • @MoinakDebnath:超过时间限制?所以你确实有运行代码太慢了?

标签: c++ product division number-theory


【解决方案1】:

素数分解所有的素数。

对于每个查询值,构建N维数组,其中N是查询值的质因数。每个维度都有 k+1 个条目,其中 k 是相应素数的幂。

绘制此数组中的每个潜在因子,将其位置增加 1。如果在数组之外,则丢弃。

使用 n 维扫描将 cdf 存储在沿每个维度的每个维度中。总共不到 40 个条目,所以这应该足够快。

对每个潜在因素的“逆”位置求和。如果 I_j 和 I_j 无效,请通过将素数加倍并减一来手动检查。

您可以预先考虑每个目标或每个源,并构建一个巨大的数组。但这可能太远了。

【讨论】:

    【解决方案2】:

    像这样快速拍摄:

    您可以“预编译”一个列表 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
    

    【讨论】:

      【解决方案3】:

      A 可能会这样做:

      1. 创建一个哈希映射,H,其中包含集合中所有 A[i]A[j] 倍数的产品 一个。 (如果您愿意,可以改用二维数组)。
      2. 让一个零初始化的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;
      }
      

      See a Demo

      【讨论】:

      猜你喜欢
      • 2021-11-11
      • 1970-01-01
      • 2018-09-16
      • 2019-04-19
      • 1970-01-01
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 2021-04-09
      相关资源
      最近更新 更多