📌  相关文章
📜  Q 查询的给定范围内 K 的可能余数计数(1)

📅  最后修改于: 2023-12-03 15:04:43.126000             🧑  作者: Mango

题目描述

给定一个长度为n的正整数数组,对于每个询问,给出左右两边界l,r和一个数K,求[l,r]中有多少个数模K的余数是满足[1,p-1]之间。

输入格式

第一行包含一个整数n,表示数组长度

第二行包含n个空格隔开的整数,表示数列a1,a2,…,an

第三行包含一个整数q,表示询问次数

接下来q行,每行包含三个整数l,r,K,表示一个询问

输出格式

共q行,每行一个整数,表示相应询问的结果

数据范围

1≤n,q≤10^5, 1≤ai,K≤10^6, 1≤l,r≤n,

输入样例

5 1 2 3 4 5 3 1 5 2 2 4 3 3 5 1

输出样例

2 1 3

C++ 代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;

int n, m;
int a[N];
int cnt[N];

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    scanf("%d", &m);
    while (m --)
    {
        memset(cnt, 0, sizeof cnt);
        int l, r, k;
        scanf("%d %d %d", &l, &r, &k);
        for (int i = l; i <= r; i ++) cnt[a[i] % k] ++;
        int res = 0;
        for (int i = 1; i < k; i ++) if (cnt[i]) res ++;
        printf("%d\n", res);
    }
    return 0;
}
题目解析

这道题目就是模模运算和模范围的问题,但是数据范围很大,n和m都是$10^5$,不能直接枚举,考虑如果对于每个询问都去计算[l,r]中的每个数对k的模结果,求余结果,再判断是否在[1,k-1]的区间中,这么算时间复杂度已经达到了$n \cdot m \cdot k$ 左右,显然无法承受。

所以肯定是要找规律减少计算量的,考虑如果我们对数组a中每个数对k的模结果计数,再把有计数的位置加起来,令sum为这个量,那么此时sum就为[l,r]中能够被K整除的数的个数。

因此再来遍历一遍cnt数组,把对应的个数大于0的位置加起来,就是实际上满足条件的数的个数的数量。

最终的时间复杂度就是$n \cdot m$的复杂度,进一步地优化了时间。