236小U的数组权值计算 O(n) 做法

134 阅读1分钟

问题描述

小 R 定义一个数组的“权值”为相邻两数乘积为奇数的对数。给定一个整数 n,表示数组的长度,即需要求从 1 到 n 的所有排列的权值之和。每个排列包含从 1 到 n 的每个正整数且仅出现一次。由于结果可能非常大,答案需要对 109+710^9 + 7 取模。

题解

  1. 奇数对的选择:

    • 只有两个奇数的乘积为奇数
    • 在 1 到 n 的数中,奇数的个数为 n/2\lceil n/2 \rceil
    • 选择两个不同的奇数有 n/2×(n/21)\lceil n/2 \rceil \times (\lceil n/2 \rceil - 1) 种方法。
  2. 位置的安排:

    • 一个奇数对可以出现在排列中的 n-1 个相邻位置中的任意一个位置。
    • 除去选定的两个奇数后,剩下的 n-2 个元素可以有(n2)!(n-2)!种排列方式。
  3. 总计:

    • 将以上部分相乘,得到总权值之和: a(n) = n/2×(n/21)×(n1)!\lceil n/2 \rceil \times (\lceil n/2 \rceil - 1) \times (n-1)!
mod = int(1e9 + 7)
from math import ceil
def solution(n: int) -> int:
    res = ceil(n / 2) * ceil(n / 2 - 1)
    for i in range(1, n): res = (res * i) % mod
    return res


if __name__ == '__main__':
    print(solution(5) == 144)
    print(solution(3) == 4)
    print(solution(6) == 720)

复杂度分析: 时间复杂度:O(n)O(n) 空间复杂度:O(1)O(1)