阶乘逆元板子

const int maxn=4e5+7;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
ll fac[maxn];///阶乘
ll inv[maxn];///阶乘逆元
ll quick_pow(ll a,ll b,ll p)
{
   ll ans=1;
   while (b)
   {
    if (b&1)///b为奇数
        ans=(ans*a)%p;
     a=(a*a)%p;///b为偶数
     b>>=1;
   }
   return ans;
}
void init()
{
    fac[0] = 1;
    for (int i = 1; i < maxn; i++)
    {
        fac[i] = fac[i - 1] * i % mod;
    }
    inv[maxn - 1] = quick_pow(fac[maxn - 1],mod - 2,mod);
    for (int i = maxn - 2; i >= 0; --i)
    {
        inv[i] = inv[i + 1] * (i + 1) % mod;
    }
}
int prime[maxn+2];//prime[0]记录当前为止找到的素数的个数,1~n存找到的素数
int visit[maxn+2];//0表示是素数
void Prime()
{
    memset(visit,0,sizeof(visit));
    memset(prime, 0,sizeof(prime));
    for (int i = 2; i <= maxn; i++)
    {
        if (visit[i]==0)
        {
            prime[++prime[0]] = i;//记录素数的个数,同时存找到的素数
        }
        for (int j = 1; j <=prime[0] && i*prime[j] <= maxn; j++)//遍历每一个已找到的素数
        {
            visit[i*prime[j]] = prime[j];//这个素数的倍数是合数
            if (i % prime[j] == 0)//因为每个数只被它的最小质因子筛一次,在此之后的质数不用筛,以后会筛
            {
                break;
            }
        }
    }
}
ll c(ll n,ll m)///Cnm
{
    if (m>n||n<0||m<0)return 0;
    if(n < maxn) return (fac[n] * inv[m] % mod * inv[n - m] % mod)%mod;
	//c(n,m) = n!/m!*(n-m)!
}
齐芒行,川锋明!
原文地址:https://www.cnblogs.com/qimang-311/p/13365854.html