题目来源:牛客,阿里巴巴编程题(2星),第10题
题目描述
题解
这道题的本质就是实现 C n m \text{C}_n^m Cnm,ans = C N 2 a \text{C}_{N^2}^a CN2a+ C N 2 − a b \text{C}_{N^2-a}^b CN2−ab+ C N 2 − a − b c \text{C}_{N^2-a-b}^c CN2−a−bc。
代码如下:
import math
p = 998244353
def power(x,y): #求x的y次方
global p
res = 1
while y:
if y % 2 != 0:
res *= (x%p)
y >>= 1
x *= (x%p)
return res
def comb(n,m): # Cnm
global p,power
a = (math.factorial(n))%p
b = (power(math.factorial(m),(p-2)))%p
c = (power(math.factorial(n-m),(p-2)))%p
return a*b*c%p
def main():
global comb,p
N,a,b,c,d = map(int,input().split())
ans = comb(N*N,a)*comb(N*N-a,b)*comb(N*N-a-b,c)%p
print(ans)
return
if __name__ == '__main__':
main()
知识点:实现组合数 C n m \text{C}_n^m Cnm计算的三种方法
法一:直接计算
C n m \text{C}_n^m Cnm的计算公式为 n ! m ! ∗ ( n − m ) ! \frac{n!}{m!*(n-m)!} m!∗(n−m)!n!。当n和m较小时,可直接利用该公式进行计算:
import math
ans = math.factorial(n)//(math.factorial(m)*math.factorial(n-m))
新姿势:math.factorial(n)
返回n的阶乘;
法二:用定义式递归
递推表达式: C n m = C n − 1 m − 1 + C n − 1 m \text{C}_n^m=\text{C}_{n-1}^{m-1}+\text{C}_{n-1}^m Cnm=Cn−1m−1+Cn−1m。
所以,代码实现如下:
注意递归出口
def comb(n,m):
if m==1:
return n
elif m==n:
return 1
else:
return comb(n-1,m-1)+comb(n-1,m)
法三:逆元+快速幂
当n和m较大时,题目一般会要求返回对p取模之后的结果,这时问题就转换成求解(a/b)%p的结果,其中,a为n!,b为m!*(n-m)!。
为求解(a/b)%p,首先介绍逆元的概念:
当a和p互素,若b满足(a*b)%p=1,则b为a%p的逆元。
有了这个概念,我们就可以对(a/b)%p做如下转换:
假设c为b%p的逆元,即(c*b)%p=1,则:
(a/b)%p = (a/b*1)%p
= (a/b*(b*c)%p)%p
= a*c%p
= (a%p)*(c%p)%p
这样,(a/b)%p就转换成了乘法问题。
下面,利用费马小定理求解逆元:
费马小定理:当p为质数,且a%p!=0时,则 a p − 1 % p = 1 a^{p-1}\%p=1 ap−1%p=1。
也就是说, a p − 2 ∗ a % p = 1 a^{p-2}*a\%p=1 ap−2∗a%p=1,即 a p − 2 a^{p-2} ap−2是a%p的逆元。
现在,再利用快速幂计算 a p − 2 a^{p-2} ap−2,之后就可大功告成。
总结一下,我们要求解的目标是n!/(m!*(n-m)!)%p,
首先,我们需要求解(m!*(n-m)!)%p的逆元,也就是分别求解m!%p和(n-m)!%p的逆元,记作b和c。
接着,当求解完逆元b和c,即可计算n!/(m!*(n-m)!)%p,即n!*b*c%p。
总结起来,利用逆元+快速幂计算 C n m \text{C}_n^m Cnm的代码如下:
import math
p = 998244353
def power(x,y): #求x的y次方,快速幂
global p
res = 1
while y:
if y % 2 != 0:
res *= (x%p)
y >>= 1
x *= (x%p)
return res
def comb(n,m):
global p,power
a = (math.factorial(n))%p
b = (power(math.factorial(m),p-2))%p
c = (power(math.factorial(n-m),p-2))%p
return a*b*c%p
ref:https://blog.csdn.net/bianxia123456/article/details/105151104;