【问题标题】:Big number factorial modulo big prime number大数阶乘模大素数
【发布时间】:2014-07-20 12:00:30
【问题描述】:

我需要计算一个大数 (

long long unsigned modulo(long long unsigned nr){
    return nr % 1000000007;
}

long long unsigned fact(long long unsigned nr){
    if(nr)return modulo(nr * fact(nr - 1));
    else return 1;
}

更新 1:

long long unsigned fact(long long unsigned nr){
    long long unsigned r = nr;
    while(--nr){
        r = modulo(r * nr);
    }
    return r;
}

【问题讨论】:

  • 使用模运算 modmul 而不是 * ,不要使用 N 次递归以避免堆/堆栈垃圾/溢出,并尽可能使用快速阶乘(例如,这个 stackoverflow.com/a/18333853/2521214 是我的芽需要表素数最多 N ,但还有更多...)
  • 别忘了,你可以在O(sqrt(n))时间计算。

标签: c algorithm modulo factorial


【解决方案1】:

这是因为您的实现使用递归。对于小数,它可以正常工作,但对于大数,它会溢出堆栈。

这一行

if(nr)return modulo(nr * fact(nr - 1));

创建nr 堆栈帧。由于堆栈空间非常有限,输入较大的数字会导致堆栈溢出。

更改您的实现以使用阶乘的迭代计算来避免崩溃。

修复崩溃后,请处理数字溢出。不要在计算出阶乘后计算模数,而是在计算的每个步骤中继续应用模数。

【讨论】:

  • 那无济于事。计算100万!无论递归如何,都会溢出
  • 我认为问题中写的代码没有任何数字溢出问题。
  • @PascalCuoq +1,忽略我的评论,这段代码不正确
  • 有什么方法可以更快吗?我在算法中使用此代码解决问题,当我尝试对其进行测试时,测试人员说超出时间限制。 (内存限制为 8192 KB,执行时间限制为 0.7 秒 - 在一次执行中,我正在执行三个 fact() 调用)
  • @Zack 这是一个demo on ideone,它在 0.34 秒内计算出 10,000,000 的答案。
【解决方案2】:

在最坏的情况下,您将生成 1 000 000 个递归调用,每个调用都需要堆栈的一部分用于其激活记录。

堆栈大小通常限制为 1MB,一旦每次调用使用 2B(实际上,您将使用超过 2 个字节,通常是 32B 或更多),您将使用超过 1MB 的堆栈,导致分段错误。

【讨论】:

    【解决方案3】:
    /* C code to implement factorial of large number */
    #include<stdio.h>
    int main(){
    int a[200],index,i,j,n,tmp,counter=0;
    printf("\n Enter the no : ");
    scanf("%d",&n);
    a[0]=1;
    index=0;
    //Calculation Loop
    for(j=n;j>=2;j--){
    tmp=0;
    /* This Loop is used to multiply the numbers */
    for(i=0;i<=index;i++){
        tmp=(a[i]*j)+tmp; // here tmp is carry digir which should be added to next multiplied value
        a[i]=tmp%10; // Extracting last digit of number
        tmp=tmp/10; // Extracring carry digir
    }
    // This loop helps you to extract digits from last calculated carry digits
    /* Supposse last carry digit is 25 then we must extract each digit( 5 & 2) and store it into array */
    while(tmp>0){
        a[++index]=tmp%10;
        tmp=tmp/10;
    }
    }
    //Loop to print output of calculated factorial
    printf("\n The factorial of %d is : \n",n);
    for(i=index;i>=0;i--)
    printf("%d",a[i]);
    return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-10-17
      • 1970-01-01
      • 1970-01-01
      • 2020-05-29
      • 2016-01-04
      • 1970-01-01
      • 2021-08-11
      • 1970-01-01
      相关资源
      最近更新 更多