C++ 计数乘积为x的三元组数

C++ 计数乘积为x的三元组数,c++,algorithm,data-structures,C++,Algorithm,Data Structures,给定一个整数数组和一个整数x,我需要找到数组中乘积为x的无序三元组的数目。我有一个强力O(n3)解决方案: int solve(int a[], int n, int x) { int ans = 0; for (int i = 0; i < n; ++i) for (int j = i+1; j < n; ++j) for (int k = j+1; k < n; ++k) if(a[i]

给定一个整数数组和一个整数x,我需要找到数组中乘积为x的无序三元组的数目。我有一个强力O(n3)解决方案:

int solve(int a[], int n, int x) {
    int ans = 0;
    for (int i = 0; i < n; ++i)
        for (int j = i+1; j < n; ++j)
            for (int k = j+1; k < n; ++k)
                if(a[i]*a[j]*a[k] == x)
                    ans++;
    return ans;
}
intsolve(inta[],intn,intx){
int ans=0;
对于(int i=0;i
有没有一种更快的方法,比如在O(n logn)时间内

  • 将a中的所有元素放入哈希表中--O(n)
  • 因式分解x--O(sqrt(x))
  • 构建x--O(3^log(x))的除数的所有可能的三元组
  • 在哈希表中搜索这些三元组--O(1)
  • 如果存在三元组,则增加计数器--O(1)

  • 运行时间现在将取决于素数pf(x)的数量,特别是O(3^pf(x))。由于x的素数因子的数量可以用log(x)来限定,这就产生了O(3^log(x)),这实际上可以进一步简化,具体取决于精确的基数。

    代码是java的,但正如您所知,其思想是一样的

    时间复杂度为
    O(n^1.5)
    。我用10^5个元素进行了检查,结果正常。 这个想法是-

    • 将列表中的所有元素及其计数放入映射中
    • 现在,如果
      a[i]*a[j]*a[k]==x
      true
      ,那么这三个都必须是
      x
      的因子。因此,如果
      x%a[i]==0
      ,我会在
      sqrt(x/a[i])
      时间中查找所有乘以
      x/a[i]
      的因子(对)
    • 因为,我们对列表中的每个元素都这样做,复杂性如下-

      • O(n)用于向映射添加元素
      • O(n*n^0.5)用于检查三胞胎
    所以,总复杂度=O(n)+O(n*n^0.5)=O(n^1.5)渐近

    假设-我认为元组是数组中具有不同索引的三元组

    更新-当前代码将相同索引的不同排列视为不同元组。您可以通过将三元组索引(pipe)分隔连接起来,将它们存储为字符串的附加映射来修复此问题

    import java.util.*;
    import java.io.*;
    class Solution{
        public static void main(String args[]) throws IOException{
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            int n = Integer.parseInt(br.readLine());
            String[] s = br.readLine().split("\\s");
            int[] a = new int[n];
            for(int i=0;i<n;++i){
                a[i] = Integer.parseInt(s[i]);
            }
            int x = Integer.parseInt(br.readLine());
            System.out.println(solve(a,n,x));
        }
    
        private static long solve(int a[], int n, int x) {
            long tuples = 0;
            Map<Integer,Integer> elements = new HashMap<>();
    
            for(int i=0;i<a.length;++i){
                elements.put(a[i],elements.getOrDefault(a[i],0) + 1);
            }
    
            for(int i=0;i<a.length;++i){
                if(x%a[i] == 0){
                    tuples += factorPairs(x/a[i],elements,a[i]);
                }
            }
    
            return tuples;
        }
    
        private static long factorPairs(int x,Map<Integer,Integer> elements,int factor1){
            long pairs = 0;
            for(int i=1;i*i<=x;++i){
                int second = i;
                int third = x/i;
                if(second*third == x && elements.containsKey(second) && elements.containsKey(third)){
                    long second_cnt = elements.get(second) - (second == factor1 ? 1 : 0);
                    long third_cnt = elements.get(third) - (third == factor1 ? 1 : 0);
                    pairs += second_cnt * third_cnt;
                }
            }
    
            return pairs;   
        }
    }
    
    import java.util.*;
    导入java.io.*;
    类解决方案{
    公共静态void main(字符串args[])引发IOException{
    BufferedReader br=新的BufferedReader(新的InputStreamReader(System.in));
    int n=Integer.parseInt(br.readLine());
    字符串[]s=br.readLine().split(\\s);
    int[]a=新的int[n];
    
    对于(int i=0;我给我们举个例子。对于
    nlog(n)
    ,排序并可能进行二进制搜索。一旦对数字进行排序,可以在线性时间内完成。要改进O(n^3),需要一些假设。发布你的暴力O(n^3)解决方案和样本数据集以及预期的输出将使许多假设更加清晰。问题很广泛。@SaiBot:我认为OP想要三元组,而不是成对的。你可以将其设为O(n^2)。它不是pf(x)^3吗?不,你不想从pf(x)中选择3个元素,但你想从pf(x)中构建3个组数字。从N个元素中生成3个组有3个^ ^可能性。@ Juviang-On,我在这里混合了主要因子和除数。我的坏。是的,我也感到困惑:)对不起,不是一个大的C++程序员。另外,StAdSoad不应该是一个编码服务。试试你自己,如果你遇到问题,人们会帮助。