题目来源:牛客,阿里巴巴编程题(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;