Having difficulty in computing factorial(n) mod m, when n gets large

▼魔方 西西 提交于 2019-12-11 18:13:42

问题


I am trying to compute factorial of large numbers mod a large prime number.

arr[] stores the value of the factorials for various numbers

If I calculate fact(32570) first and then print arr[1] and arr[2], then that works.

If I calculate fact(32571) first and then print arr[1] and arr[2], then that does not work.

However, calculating only fact(32571) works.

I really cannot debug this code.

Also, calculating fact(32572) independently does not work. But, if I calculate fact(32572) after finding fact(32571) then that works okay.

Whats going on here?

#define LL unsigned long long
#define ull unsigned long long

const LL mod=1000000009;

LL arr[1048580];

inline ull mulMod(ull a,ull b,ull c)
{
    if(a<=1000000000ULL && b<=1000000000ULL)
    {
        //cout<<((a%c)*(b%c))%c<<endl;
        ull ret = ((a%c)*(b%c))%c;         //also giving segmentation fault
        return ret;
    }
    ull ret = 0ULL; a=a%c;

    while(b > 0ULL)
    {
        if(b&1ULL) ret = ((ret%c)+(a%c))%c;
        a = (a<<1ULL)%c;
        b>>=1ULL;
    }
    return ret%c;
}

LL fact(LL num)
{
    if(arr[num]==0)
    {
        arr[num]=mulMod(num,fact(num-1),mod);    //gives segmentation fault
        return arr[num];
    }

    return arr[num];
}


int main()
{
    arr[0]=1;
    // does not work
    //    cout<<fact(32571)<<endl;
    //    cout<<arr[1]<<" "<<arr[2]<<endl;

    //works
    //    cout<<fact(325)<<endl;
    //    cout<<arr[1]<<" "<<arr[2]<<endl;

    //also works
    cout<<fact(32571)<<endl;
}

回答1:


My guess is that you're running out of stack. Every (recursive) call to fact() pushes a few values onto the program's stack (return address, saved registers mandated by ABI, etc.). The size of the stack is fixed (depending on your OS, you can change it more or less easily; see ulimit if you're using a Bourne-like shell), so eventually, when you have deep recursion like this, there is a “straw that breaks the camel's back”, and when you call one more time, there's no stack left and your program exits with an error message of some kind (e.g. “Segmentation violation” on Unix-like OSs).

As Tristan correctly comments below, an iterative factorial algorithm does not have this problem.




回答2:


Is 32571 the first integer for which it occurs?

Have you tried out what happens when you change if(a<=1000000000ULL && b<=1000000000ULL) to if(a<mod && b<mod)?



来源:https://stackoverflow.com/questions/22254901/having-difficulty-in-computing-factorialn-mod-m-when-n-gets-large

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!