大数阶因数模数大素数

问题描述 投票:3回答:3

我需要计算一个大数的阶乘(<= 1.000.000),我需要结果模数1000000007.我写了以下内容,但它在运行时生成错误(test.exe已停止工作)。它仅适用于小数字。

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;
}
c algorithm modulo factorial
3个回答
7
投票

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

这条线

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

创建nr堆栈帧。由于堆栈空间非常有限,因此输入大量数据会导致堆栈溢出。

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

完成崩溃后,处理数字溢出。不是在计算阶乘之后计算模数,而是在计算的每个步骤继续应用模数。


2
投票

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

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


0
投票
/* C code to implement factorial of large number */
#include&lt;stdio.h&gt;
int main(){
int a[200],index,i,j,n,tmp,counter=0;
printf("\n Enter the no : ");
scanf("%d",&amp;n);
a[0]=1;
index=0;
//Calculation Loop
for(j=n;j&gt;=2;j--){
tmp=0;
/* This Loop is used to multiply the numbers */
for(i=0;i&lt;=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 &amp; 2) and store it into array */
while(tmp&gt;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&gt;=0;i--)
printf("%d",a[i]);
return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.