如何找到给定范围内除以给定数字时具有一定余数的值的数量?

Posted

技术标签:

【中文标题】如何找到给定范围内除以给定数字时具有一定余数的值的数量?【英文标题】:How to find the number of values in a given range that has a certain remainder when divided by a given number? 【发布时间】:2019-11-22 19:12:16 【问题描述】:

给定四个整数N, L, R and Rem。我必须找到L and R(含)之间的值的数量,当除以N 时得到余数Rem

例如:如果N = 3, L = 2, R = 10 and Rem = 1,那么在这个范围内除以3余数为1的数字是4, 7, 10。所以,答案是 3。

这是我编码的蛮力方法:

int main() 
    int N, L, R, Rem;
    cin >> N >> L >> R >> Rem;

    int Ans = 0;
    for (int i = L; i <= R; i++) 
        if (i % N == Rem)
            Ans++;
    
    cout << Ans << endl;

解决这个问题的更好方法是什么?

【问题讨论】:

提示:如果你有两个数字,AB,然后你将它们除以 N,它们的余数相同,然后 A + NC = B 某个整数 C 你必须减少循环,而不是 i++ 使用 i += N 【参考方案1】:

首先,在[0, n)范围内找到此类值的数量:

template<class T>
T count(T n, T div, T rem) 
    assert(rem < div);
    return (n + div - rem - 1) / div;

然后减去,[0, max + 1) \ [0, min) = [min, max]:

template<class T>
T count(T min, T max, T div, T rem) 
    assert(min >= 0);
    assert(min <= max);
    return count(max + 1, div, rem) - count(min, div, rem);


显然,它不适用于负值。 OP 将输入指定为整数,而不是正整数。

这个答案假设所有整数都是非负数。原因很简单:我们都同意非负数的余数,但different definitions 存在负数。问题措辞没有说明应该采用哪种定义。例如,在 C++11 之前的 C++ 本身中,如果a &lt; 0b &lt; 0,标准将a % b 的结果指定为实现定义。原因在于 / 运算符在为整数操作数定义的方式上存在以下差异:

直到 C++11:

商在实现定义的方向上四舍五入。

C++11 起:

商被截断为零(小数部分被丢弃)。

因此,%std::div 可能会给出不同的结果——在 C++11 之前,后一个函数遵循“丢弃小数部分”的规则。

【讨论】:

显然,它不适用于负值。 OP 将输入指定为整数,而不是正整数。 @ciamej,添加了一些关于否定词的内容。【参考方案2】:

TLDR大概(R-L+1)/N 取+-1

例如 L=2 R=10 N=3 REM=0

数字是 3,6,9 (R-L+1)/N = (10-2+1)/3 = 9/3 = 3

这是一个准确的解决方案,带有解释,不需要循环

找到第一个大于或等于 L 且能很好地除以 N 的数

L = (L % N == rem)? L : L + (REM - L%N)

找到最后一个小于或等于 R 且能很好地除以 N 的数

R = (R % N == rem)? R : R - (N - (REM - R%N))

结果是

int result = ((R-L)/N) + 1

【讨论】:

显然,它不适用于负值。 OP 将输入指定为整数,而不是正整数。【参考方案3】:
(R - L) / N 
+ 1 if (R - L) % N ≥ (rem - L) % N

【讨论】:

以上是关于如何找到给定范围内除以给定数字时具有一定余数的值的数量?的主要内容,如果未能解决你的问题,请参考以下文章

找到给定范围内数字的最大最小差

随机数生成器不会使用输入字段中的值生成给定范围内的预期数字[重复]

如何构建具有连续值之间最大平均距离的阈值图?

Python列表如何识别给定数字在挑战问题范围内[关闭]

有没有办法使用线段树在给定范围内查找数字的频率?

如何在整数数组中查找所有有序元素对,其总和位于给定的值范围内