【问题标题】:Oveflow even when an int is mod by 10^9+7即使 int 以 10^9+7 为模,也会溢出
【发布时间】:2019-02-18 07:10:05
【问题描述】:

我为数字的阶乘编写了以下代码:

long int fac[max+1];
    fac[0]=1;


    for(int j=1;j<=max;j++)
        {
            fac[j]=(fac[j-1]*j)%1000000007;
        }


    //Printing
    for(int i=0;i<T;i++)
        {
            cout<<fac[N[i]]<<"\n";
        }

这对于 long int 非常有效,但是如果我们将数组更改为 int,我们会得到错误的答案。

请告诉我为什么当 int 的范围大于 10^9+7 时会发生这种情况。

【问题讨论】:

  • 请注意 long int 与 Windows 中的 int 相同。如果您想要有保证的 64 位类型,请使用 int64_tlong long,前提是您可以接受至少 64 位的类型。

标签: c++ int overflow


【解决方案1】:

int fac[max+1];fac[j-1] * jint * int,结果为 int

如果你溢出,你有 UB,即使没有签名,你也会丢失数据。

使用long int fac[max+1];,则fac[j-1] * jlong int * long intint -> long intj),结果为long int

【讨论】:

    【解决方案2】:

    我们知道 0 ≤ fac[j - 1] 9 + 7。但 fac[j - 1] * j 将达到 j 倍以上,而 long 偶尔只有 32 位长(Windows)。您可以放入 32 位数字的绝对最大值为 4294967295,仅为模数的四倍左右。

    考虑使用unsigned long long 而不是long int - 这应该可以工作到j > 234

    事实上,鉴于(a * b) % Nmathematically equivalent(a % N) * (b % N)一旦你将long int 替换为unsigned long long,你就可以重写

    fac[j] = (fac[j - 1] * j) % 1000000007
    

    fac[j] = (fac[j - 1] * (j % 1000000007)) % 1000000007
    

    那么,因为 1000000007264,你应该可以一直持续下去(虽然你最终会用完 fac 的空间,当然)。

    【讨论】:

      猜你喜欢
      • 2020-07-09
      • 2021-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-20
      • 1970-01-01
      相关资源
      最近更新 更多