C++ 如何在C+中找到模100000007的大数的阶乘+;?

C++ 如何在C+中找到模100000007的大数的阶乘+;?,c++,c,math,coding-style,modulo,C++,C,Math,Coding Style,Modulo,求大数模100000007的阶乘 Python或java中的p>,没有问题,但是C++中有溢出约束。 这是我尝试过的代码: #include<iostream> #define ull long long int #define mod 1000000007 ull fact(ull n) { if(n==1 || n==0) return 1; return ((n%mod)*(fact(n-1)%mod)%mod); } i

求大数模100000007的阶乘

Python或java中的p>,没有问题,但是C++中有溢出约束。 这是我尝试过的代码:

#include<iostream>
 #define ull long long int
 #define mod 1000000007
 ull fact(ull n)
 {
           if(n==1 || n==0) return 1;
           return ((n%mod)*(fact(n-1)%mod)%mod);
 }
 int main()
 {
              cout<<fact(50000)<<endl;
              return 0;
 }
#包括
#定义长整型
#定义mod 100000007
ull事实(ull n)
{
如果(n==1 | | n==0)返回1;
返回((n%mod)*(事实(n-1)%mod)%mod);
}
int main()
{

cout检查此代码。不应该有任何问题,因为无符号long long可以轻松存储任何模值10^9+7。我的意思是,如果您使用的是模值而不是实际值,那么您为什么还要关心它?(众所周知,10^9+7可以存储在ull中)

ullans;
完整事实(int n)
{

如果(nif
x!!
=
1*3*5*7*9*11*…
,那么
2x!
=
2x!!*2^x*x!

这给了我们一个更有效的阶乘算法

template<ull mod>
struct fast_fact {
  ull m( ull a, ull b ) const {
    ull r = (a*b)%mod;
    return r;
  }
  template<class...Ts>
  ull m( ull a, ull b, Ts...ts ) const {
    return m( m( a, b ), ts... );
  }
  // calculates x!!, ie 1*3*5*7*...
  ull double_fact( ull x ) const {
    ull ret = 1;
    for (ull i = 3; i < x; i+=2) {
      ret = m(i,ret);
    }
    return ret;
  }
  // calculate 2^2^n for n=0...bits in ull
  // a pointer to this is stored statically to make calculating
  // 2^k faster:
  ull const* get_pows() const {
    static ull retval[ sizeof(ull)*8 ] = {2%mod};
    for (int i = 1; i < sizeof(ull)*8; ++i) {
      retval[i] = m(retval[i-1],retval[i-1]);
    }
    return retval;
  }
  // calculate 2^x.  We decompose x into bits
  // and multiply together the 2^2^i for each bit i
  // that is set in x:
  ull pow_2( ull x ) const {
    static ull const* pows = get_pows();
    ull retval = 1;
    for (int i = 0; x; ++i, (x=x/2)){
      if (x&1) retval = m(retval, pows[i]);
    }
    return retval;
  }
  // the actual calculation:
  ull operator()( ull x ) const {
    x = x%mod;
    if (x==0) return 1;
    ull result = 1;
     // odd case:
    if (x&1) result = m( (*this)(x-1), x );
    else result = m( double_fact(x), pow_2(x/2), (*this)(x/2) );
    return result;
  }
};
template<ull mod>
ull factorial_mod( ull x ) {
  return fast_fact<mod>()(x);
}
模板
结构快速事实{
ull m(ull a,ull b)常数{
ull r=(a*b)%mod;
返回r;
}
模板
ull m(ull a,ull b,Ts…Ts)常数{
返回m(m(a,b),ts…);
}
//计算x!!,即1*3*5*7*。。。
ull双_事实(ull x)常数{
ull-ret=1;
对于(ull i=3;i

更快的版本可以重用
x!!
的结果,因为这些结果经常重复

,通过合理巧妙地缓存
x!!
值,其速度大约是上述大n缓存速度的2倍。
每次调用
double\u factorial(n)
都会创建lg k缓存项,其中k是n和最大的旧缓存项之间的距离。因为k以n为界。实际上,这似乎可以减少加权的“缓存未命中”第一次调用后几乎为零:
n!!
的第一次计算注入了足够的缓存项,这样我们就不会在以后的
计算中浪费大量时间!!

这个优化版本比简单的迭代实现快41%(基本上所有的时间都花在计算第一个
n!!


进一步的改进可能包括使第一个
x!!
计算更快,优化缓存可能会带来一些微小的改进。下一个问题:如何使
x!!
更快?

“但是输出无效。”请仔细说明一下吗?我猜你正在调用堆栈溢出。阶乘很快溢出很长时间。这就是为什么你需要使用任意精确的数学库。C++有很多。@ HANSPASTANT:但是,这是一个模数减少的小数字,对于32位的值来说是不应该有的。你的代码不应该有任何溢出。,给出了与更合理的迭代版本相同的结果。应该没有溢出,因为在减少模
mod
后,两个乘法器都适合32位,因此乘积适合64位(并且
long
至少有64位)。递归可能会溢出堆栈。你所说的“无效”到底是什么意思?你会得到什么结果?你期望得到什么(为什么)?@BenjaminTrent.:这就是添加代码的原因。无需进行任何递归调用,将帧推入堆栈并导致堆栈溢出。简单的迭代即可获得结果。@BenjaminTrent.:我已修改了我的答案,以便更清楚。我还提到了您讨论过的问题。希望它能使答案完整。@rcgldr、 :我已经检查过了。10^9+7是一个素数。您可能知道这是一个众所周知的数字,在许多竞争性编程问题中经常出现,否则在某些情况下它会给出错误的输出。次要:使用
for(int I=n;I>=2;I--)
,然后使用
ull fact(int\u MAX)避免无限循环
@chux.:你能详细说明一下这一点吗?(for-one循环)。然后你要检查一下(n
template<ull mod>
struct fast_fact {
  ull m( ull a, ull b ) const {
    ull r = (a*b)%mod;
    return r;
  }
  template<class...Ts>
  ull m( ull a, ull b, Ts...ts ) const {
    return m( m( a, b ), ts... );
  }
  // calculates x!!, ie 1*3*5*7*...
  ull double_fact( ull x ) const {
    ull ret = 1;
    for (ull i = 3; i < x; i+=2) {
      ret = m(i,ret);
    }
    return ret;
  }
  // calculate 2^2^n for n=0...bits in ull
  // a pointer to this is stored statically to make calculating
  // 2^k faster:
  ull const* get_pows() const {
    static ull retval[ sizeof(ull)*8 ] = {2%mod};
    for (int i = 1; i < sizeof(ull)*8; ++i) {
      retval[i] = m(retval[i-1],retval[i-1]);
    }
    return retval;
  }
  // calculate 2^x.  We decompose x into bits
  // and multiply together the 2^2^i for each bit i
  // that is set in x:
  ull pow_2( ull x ) const {
    static ull const* pows = get_pows();
    ull retval = 1;
    for (int i = 0; x; ++i, (x=x/2)){
      if (x&1) retval = m(retval, pows[i]);
    }
    return retval;
  }
  // the actual calculation:
  ull operator()( ull x ) const {
    x = x%mod;
    if (x==0) return 1;
    ull result = 1;
     // odd case:
    if (x&1) result = m( (*this)(x-1), x );
    else result = m( double_fact(x), pow_2(x/2), (*this)(x/2) );
    return result;
  }
};
template<ull mod>
ull factorial_mod( ull x ) {
  return fast_fact<mod>()(x);
}