在一场运动会中有n个国家的队伍参赛,每支队伍5个运动员,所以一共有5n个运动员。现对这5n个运动员排成一列,要求每位远动员能够挨着他的同胞站,问有多少种排列组会方法,最后输出的答案除以1000000007取余即可。北邮人论坛链接
#这部分是通用的基础函数
def A(n):
return n*A(n-1) if n>0 else 1
def C(n,m):
return A(n)/(A(n-m)*A(m)) if m>0 else 1
def mod(n):
return n%1000000007
def queue(n):
sum = 0
for i in range(n+1):
sum = C(n,i)*A(n+i) - sum
k = pow(120,n)
return mod(mod(k)*mod(sum))
n = raw_input('input n:')
print queue(int(n))
方法二:用标准的容斥原理:
#这部分是通用的基础函数
def A(n):
return n*A(n-1) if n>0 else 1
def C(n,m):
return A(n)/(A(n-m)*A(m)) if m>0 else 1
def mod(n):
return n%1000000007
#第二种写法
def queue(n):
sum = 0
for i in range(n+1):
if i%2==1:
sum -= A(2*n-i)*C(n,n-i)
else:
sum += A(2*n-i)*C(n,n-i)
k=1
for i in range(n):
k = mod(k*120)
return mod(mod(k)*mod(sum))
#这种写法是比较标准的容斥原理 由最全面的结果开始进行排除
#这部分是通用的基础函数
def A(n):
return n*A(n-1) if n>0 else 1
def C(n,m):
return A(n)/(A(n-m)*A(m)) if m>0 else 1
def mod(n):
return n%1000000007
#第一种写法
def calc(i,n,s):
if i==0:
return A(n)*C(n,0)
sum = A(n+i)*C(n,i)
for j in range(i):
sum -= s[j]*C(n-j,i-j)*pow(2,i-j)
return sum
def queue(n):
s = [0]*int(1e5)
sum = 0
for i in range(n+1):
s[i] = calc(i,n,s)
sum += s[i]
k=1
for i in range(n):
k = mod(k*120)
return mod(mod(k)*mod(sum))
#这种写法是计算n个国家5人相连,n-1个国家5人相连,一个国家2,3人相连等每种情况的有效排序,算是很麻烦了,不推荐