bluecode-好排列的数量计算

31 阅读1分钟

问题描述

小R正在研究一种特殊的排列,称为“好排列”。一个排列被称为“好排列”,当且仅当其中所有相邻的两个数的乘积均为偶数。现在给定一个正整数 nn,小R想知道,长度为 nn 的好排列共有多少种。由于结果可能非常大,你需要将结果对 109+7109+7 取模后输出。


测试样例

样例1:

输入:n = 2
输出:2

样例2:

输入:n = 3
输出:2

样例3:

输入:n = 5
输出:12

#include <iostream>
#include <vector>
using namespace std;

const int MOD = 1e9 + 7;
const int MAXN = 100005;

vector<long long> fac(MAXN), inv_fac(MAXN);

// 快速幂
long long qpow(long long a, long long b) {
  long long res = 1;
  while (b) {
    if (b & 1)
      res = res * a % MOD;
    a = a * a % MOD;
    b >>= 1;
  }
  return res;
}

// 初始化阶乘和逆元
void init() {
  fac[0] = inv_fac[0] = 1;
  for (int i = 1; i < MAXN; ++i) {
    fac[i] = fac[i - 1] * i % MOD;
    inv_fac[i] = qpow(fac[i], MOD - 2);
  }
}

long long C(int n, int k) {
  if (k < 0 || k > n)
    return 0;
  return fac[n] * inv_fac[k] % MOD * inv_fac[n - k] % MOD;
}

int solution(int n) {
  // PLEASE DO NOT MODIFY THE FUNCTION SIGNATURE
  static bool initialized = false;
  if (!initialized) {
    init();
    initialized = true;
  }

  int odd_cnt = (n + 1) / 2;
  int even_cnt = n / 2;

  if (odd_cnt > even_cnt + 1)
    return 0;

  long long res = C(even_cnt + 1, odd_cnt);
  res = res * fac[odd_cnt] % MOD;
  res = res * fac[even_cnt] % MOD;
  return (int)res;
}

int main() {
  std::cout << (solution(2) == 2) << std::endl;
  std::cout << (solution(3) == 2) << std::endl;
  std::cout << (solution(5) == 12) << std::endl;
}