好排列的数量计算
——第一次写难度等级困难的题目,简单记录;
引言
在一个排列中,如果所有相邻两个数的乘积均为偶数,这样的排列被称为“好排列”。给定一个正整数 ( n ),我们需要计算长度为 ( n ) 的好排列的数量,并将结果对取模后输出。本文将详细解析这个问题,探讨其背后的数学原理和算法实现。
问题背景
排列是组合数学中的一个重要概念,指的是从一组元素中选取若干个元素,并按照一定的顺序排列。在本题中,我们需要关注的是排列中相邻两个数的乘积是否为偶数。偶数乘以任何整数都是偶数,因此,为了使相邻两个数的乘积为偶数,至少有一个数必须是偶数。
初步思路
要解决这个问题,我们需要找到长度为 ( n ) 的排列中,所有相邻两个数的乘积均为偶数的排列数量。由于乘积为偶数,至少有一个数必须是偶数。因此,我们可以利用奇数和偶数的分布来解决问题。
数学原理
- 奇数和偶数的分布:•假设 ( n ) 个数中有 ( e ) 个偶数和 ( o ) 个奇数,其中 ( e + o = n )。•为了使相邻两个数的乘积均为偶数,奇数必须被偶数隔开。2. 排列方式:•如果 ( n ) 是偶数,所有数都可以是偶数,或者奇数和偶数交替排列。•如果 ( n ) 是奇数,最后一个数必须是偶数,前面的数可以是奇数和偶数交替排列。3. 计算排列数:•对于偶数 ( n ),排列方式有两种: •所有数都是偶数:排列数为 ( e! )。•奇数和偶数交替排列:排列数为 。•对于奇数 ( n ),排列方式也有一种: •奇数和偶数交替排列,最后一个数必须是偶数:排列数为e!*o! 。
算法设计
- 奇数和偶数的分布:假设 ( n ) 个数中有 ( e ) 个偶数和 ( o ) 个奇数,其中 ( e + o = n )。 为了使相邻两个数的乘积均为偶数,奇数必须被偶数隔开。
- 排列方式:•如果 ( n ) 是偶数,所有数都可以是偶数,或者奇数和偶数交替排列。•如果 ( n ) 是奇数,最后一个数必须是偶数,前面的数可以是奇数和偶数交替排列。
- 计算排列数:•对于偶数 ( n ),排列方式有两种: •所有数都是偶数。•奇数和偶数交替排列。•对于奇数 ( n ),排列方式也有一种: •奇数和偶数交替排列,最后一个数必须是偶数。
四、具体实现
- 偶数情况:•所有数都是偶数:排列数为 ( e! )。•奇数和偶数交替排列:排列数为 。•总排列数为 。
- 奇数情况:•奇数和偶数交替排列,最后一个数必须是偶数:排列数为e!*o! 。
def factorial(n):
result = 1
for i in range(1, n + 1):
result = (result * i) % MOD
return result
def solution(n: int) -> int:
e = n // 2 # 偶数个数
o = n - e # 奇数个数
even_factorial = factorial(e)
odd_factorial = factorial(o)
if n % 2 == 0:
# 偶数情况:所有数都是偶数 + 奇数和偶数交替排列
return (even_factorial + even_factorial * odd_factorial) % MOD
else:
# 奇数情况:奇数和偶数交替排列,最后一个数必须是偶数
return (even_factorial * odd_factorial) % MOD
if __name__ == "__main__":
print(solution(2) == 2)
print(solution(3) == 2)
print(solution(4) == 4)
print(solution(5) == 4)
- 阶乘计算:•factorial 函数计算阶乘,并对结果取模 。
- 偶数情况:•计算偶数的阶乘 even_factorial 和奇数的阶乘 odd_factorial。•总排列数为 even_factorial + even_factorial * odd_factorial,并对结果取模。
- 奇数情况:•计算偶数的阶乘 even_factorial 和奇数的阶乘 odd_factorial。•总排列数为 even_factorial * odd_factorial,并对结果取模。