废话不多数直接上图
一、组合数模板1
# c[a][b] 表示从a个糖果中选b个的方案
for i in range(N):
for j in range(i+1):
if j==0:c[i][j]=1
else:c[i][j] = (c[i-1][j]+c[i-1][j-1])%p
二、组合数模板2
#首先预处理出所有阶乘取模的余数fact[N],以及所有阶乘取模的逆元infact[N]
#如果取模的数是质数,可以用费马小定理求逆元
def qmi(a,b,p): #快速幂模板
res=1%p
while b:
if b&1:res = res*a%p
a = a*a%p
b>>=1
return res
// 预处理阶乘的余数和阶乘逆元的余数
fact[0] = infact[0] = 1;
for i in range(1,N):
fact[i] = (LL)fact[i - 1] * i % mod;
infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
三、组合数模板3
#若p是质数,则对于任意整数 1 <= m <= n,有:
#C(n, m) = C(n % p, m % p) * C(n / p, m / p) (mod p)
def qmi(a,b,p): #快速幂模板
res=1%p
while b:
if b&1:res = res*a%p
a = a*a%p
b>>=1
return res
def C(a,b,p): #通过定理求组合数C(a, b)
if a<b:return 0
x,y=1,1 #x是分子,y是分母
for i in range(b):
x = x*(a-i)%p
y = y*(i+1)%p
return x*qmi(y,p-2,p)%p
def lucas(a,b,p):
if a<p and b<p:return C(a,b,p)
return C(a%p,b%p)*lucas(a//p,b//p,p)%p
四、组合数模板4
#当我们需要求出组合数的真实值,而非对某个数的余数时,分解质因数的方式比较好用:
# 1. 筛法求出范围内的所有质数
# 2. 通过 C(a, b) = a! / b! / (a - b)! 这个公式求出每个质因子的次数。 n! 中p的次数是 n / p + n / p^2 + n / p^3 + ...
# 3. 用高精度乘法将所有质因子相乘
primes,cnt,count,st = [0]*N,0,[0]*N,[0]*N
"""分别:存储所以的质数和个数、存储每个素数出现的次数、是否被筛了"""
def get_primes(n): #线性筛所以的质数
for i in range(2,n+1):
if not st[i]:
primes[cnt]=i
cnt += 1
for j in range(cnt):
tep = primes[j]*i
if tep>n:break
st[tep]=1
if i%primes[j]==0:break
def get(n,p): #求n!中p出现的次数
res = 0
while n:
res += n//p
n//=p
return res
get_primes(a) #预处理范围内的所有质数
for i in range(cnt): #求每个质数出现的次数
p = primes[i]
count[i] = get(a,p)-get(b,p)-get(a-b,p)
res = 1
for i in range(cnt):
for j in range(count[i]):
res*=primes[j]
""" 由于Python的特性,以下方法可能不如上面直接写
res = [1]
def mul(a,b): #高精度a乘低精度b
c = []
t = 0
for i in range(len(a)):
t += a[i]*b
c.append(t%10)
t//=10
while t:
c.append(t%10)
t//=10
return c
for i in range(cnt): #用高精度乘法将所有质因子相乘
for j in range(count[i]):
res = mul(res,primes[i])
"""