组合数

递推公式

求解C(n, m)%p

费马小定理的转换

线性求inv和fac


#include<bits/stdc++.h>
#define ll long long
#define asd cout<<"!"<<endl
using namespace std;
const ll maxn=1e6+10;//memory:20068KB!!
const ll p=1e9+7;
ll fac[maxn];
ll inv[maxn];
int a[maxn];
void fac_init()
{
    fac[0]=fac[1]=1;//both 0 1 initiate
    for (int i=1;i<maxn;i++) fac[i]=(fac[i-1]*(i%p))%p;
    inv[0]=inv[1]=1;
	for(int i=2;i<maxn;i++) inv[i]=(p-p/i)*inv[p%i]%p;    
	for(int i=2;i<maxn;i++) inv[i]=inv[i]*inv[i-1]%p;//little trick
}
ll C(int i,int j)
{
	return fac[i]*inv[i-j]%p*inv[j]%p;
}
int main()
{	
    fac_init();
	int n;
	cin>>n;
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	a[0]=1000,a[n+1]=1;
	ll l=0;
	ll ans=1;
	for (int i=1;i<=n+1;i++) if (a[i])
	{
		if (a[l]<a[i]) break;
		ans=ans*C(a[l]-a[i]+i-l-1,i-l-1);//little trick?
		ans%=p;
		l=i;//little trick
	}
	cout<<ans;	
}

拓展欧几里得

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=2000+10;
const ll MAX=200+10;
const ll p=1e9+7;
ll fac[maxn];//n!
ll inv[maxn];//(n!)^(-1)
ll c[maxn][maxn];
void Exgcd(ll a, ll b, ll &x, ll &y) {
    if (!b) x = 1, y = 0;
    else Exgcd(b, a % b, y, x), y -= a / b * x;
}
void fac_init()
{
	fac[0]=1;
	for (ll i=1;i<=MAX;i++) fac[i]=(fac[i-1]*(i%p))%p;
}
ll get_inv(ll k)
{
	ll x,y;
	Exgcd(k,p,x,y);
	x=(x%p+p)%p;
	return x;
}
int main()
{
	fac_init();
	ll T;
	cin>>T;
	while (T--)
	{
		ll n,m;
		cin>>n>>m;		
		for (ll i=1;i<=MAX;i++)
		for (ll j=1;j<=i;j++)
		{
			c[i][j]=(fac[i]*get_inv((fac[i-j]*fac[j])%p))%p;
		}
		printf("%lld
",c[n][m]);	
	}	
}

费马小定理和卢卡斯定理//???
搬运:https://xienaoban.github.io/posts/36480

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll p=10007;
ll pow_mod(ll a, ll b, const int &pr)
{
	ll ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % pr;
		b >>= 1;
		a = a * a % pr;
	}
	return ans;
}
ll C_small(ll n, ll m, const int &pr)
{
	ll ans = 1;
	for (int i = 1; i <= m; i++)
	{
		ll a = (n - m + i) % pr;
		ll b = i % pr;
		ans = ans * (a * pow_mod(b, pr - 2, pr) % pr) % pr; //Fermat Theory
	}
	return ans;
}
ll C(ll n, ll m, const int &pr) // Lucas's theorem
{
	if (m == 0 || m == n) return 1;
	return C_small(n % pr, m % pr, pr) * C(n / pr, m / pr, pr) % pr;
}
int main()
{
	ll n,m;
	cin>>n>>m;
	cout<<C_small(n,m,p)<<endl;
	cout<<C(n,m,p)<<endl;
}
原文地址:https://www.cnblogs.com/reshuffle/p/12252449.html