当前位置: 首页 > 知识库问答 >
问题:

可被K整除的子阵列计数

萧德馨
2023-03-14

给定一个n个正整数的序列,我们需要计算其和可被k整除的连续子序列。

约束条件:N最多为10^6,每个元素最多为10 ^9,K最多为100

示例:设N=5,K=3,数组为1 2 3 4 1

这里的答案是4

说明:存在4个子序列,其和可被3整除,它们是:

3
1 2
1 2 3
2 3 4

我的尝试是:

long long int count=0;
for(int i=0;i<n;i++){
    long long int sum=0;
    for(int j=i;j<n;j++)
    {
        sum=sum+arr[j];
        if(sum%k==0)
        {
            count++;
        }
    }
}

但显然它的方法很差。对于这个问题,他们有更好的方法吗?请帮帮忙。

完整问题:https://www.hackerrank.com/contests/w6/challenges/consecutive-subsequences

共有2个答案

茹康裕
2023-03-14

这必须使您的计算更容易:

//Now we will move all numbers to [0..K-1]
long long int count=0;
for(int i=0;i<n;i++){
    arr[i] = arr[i]%K;
}

//Now we will calculate cout of all shortest subsequences.
long long int sum=0; 
int first(0); 
std::vector<int> beg;
std::vector<int> end;
for(int i=0;i<n;i++){
    if (arr[i] == 0)
    {
        count++; 
        continue;
    }
    sum += arr[i];
    if (sum == K)
    {
        beg.push_back(first);
        end.push_back(i);
        count++;
    }
    else
    {
        while (sum > K)
        {
            sum -= arr[first];
            first++;     
        }
        if (sum == K)
        {
            beg.push_back(first);
            end.push_back(i);
            count++;
        }
    }        
}

//this way we found all short subsequences. And we need to calculate all subsequences that consist of some short subsequencies.
int party(0);
for (int i = 0; i < beg.size() - 1; ++i)
{
    if (end[i] == beg[i+1])
    {
        count += party + 1;
        party++;
    }
    else
    {
        party = 0;
    } 
}

因此,如果max数组size=10^6并且max size of rest=99,即使您需要在简单的int32中求和所有数字,也不会有溢出。

你将花费的时间大约是O(n n)

曾阳飙
2023-03-14

这是一个快速的O(n k)解决方案:

1)让计算前缀和pref[i](对于0

2)现在我们可以计算count[i]-和i模k的前缀数(0

3) 答案是所有i的和计数[i]*(计数[i]-1)/2。

4)最好计算前缀和模数k,以避免溢出。

为什么它能工作?让我们仔细看看一个可被k整除的子数组。假设它从L位置开始,到R位置结束。它可被k整除当且仅当pref[L-1]==pref[R](模k),因为它们的差异是零模k(根据可整除性的定义)。所以对于每个固定的模,我们可以选择任何两个前缀与这个前缀和模k(并且有确切的count[i]*(count[i]-1)/2种方法可以做到这一点)。

这是我的代码:

long long get_count(const vector<int>& vec, int k) {
  //Initialize count array.
  vector<int> cnt_mod(k, 0);
  cnt_mod[0] = 1;
  int pref_sum = 0;
  //Iterate over the input sequence.
  for (int elem : vec) {
    pref_sum += elem;
    pref_sum %= k;
    cnt_mod[pref_sum]++;
  }
  //Compute the answer.
  long long res = 0;
  for (int mod = 0; mod < k; mod++)
    res += (long long)cnt_mod[mod] * (cnt_mod[mod] - 1) / 2;
  return res;
}
 类似资料:
  • 我在一次面试中有以下问题,尽管我给出了一个可工作的实现,但它不够高效。 数组A的切片是任何一对整数(P,Q),使得0≤ P≤ Q 我被要求编写的函数必须返回可被K整除的切片数。预期的时间复杂度为O(max(N, K)),空间复杂度为O(K)。 我的解决方案是最简单的,一个循环套一个循环,检查每一个切片:O(n^2) 我一直在想,但我真的不知道如何在O(max(N, K))中做到这一点。 它可能是子

  • 求其和可被K整除的最长子数组。在O(n)中可能吗?如果不是,它能比n^2更好地完成吗?

  • 给定一个数组,我想计算子数组的数量(连续的),当取的乘积不会被k整除。 例如。设 A = 和 K = 2 则使乘积不能被 K 整除的子数组数为 2: 其余的都可以被2整除。 我首先尝试计算子数组(n)(n 1)/2的总数,然后使用mod减去可被k整除的子数组的数量,但它不起作用。我该如何解决这个问题? 这(错误地)计算了乘积可被K整除的子阵列数: 一个稍微相关的问题是这个问题,但它涉及加法,因此不

  • 给定一个(未排序的)数组S和一些整数k,找到对的数量i, j使得S的范围[i... j] 我在一次采访中收到了这个问题,经过排序后只能得出一个O(nlogn)解。但是,有人告诉我有一个O(n)解。有什么想法吗?

  • 我在一次采访中遇到了以下问题。 给定一个数组,您需要找到所有元素小于给定值 k 的子数组 ,例如 现在,值小于 4 的子数组是: 注意{4}是如何重复的,但没有考虑两次。现在,代码应该返回不同子阵列的计数 在本例中为3. 另一个示例: 不同的子阵列: 我的方法是找到小于给定值k(即O(n^2))的子阵列,然后将其插入类似无序集的内容中以删除重复项。 有没有解决这个问题的有效方法?

  • 我被分配了一个任务,让我创建3个方法来创建一个数组,打印一个数组,并计算一个数组中所有可被10整除的数字。给我最大麻烦的部分是数可被10整除的数字。这是我到目前为止的代码: