【數論】[逆元,錯排]P4071排列計數

題目描述

求有多少種長度爲n的系列A,滿足以下條件:

1~n這n個數在序列中各出現一次;若第i個數a[i]的值爲i,則稱i是穩定的。序列恰有m個數是穩定的。

輸出序列個數對1e9+7取模的結果。

Solution

顯然是從N個數中選m個數穩定,剩下的錯排。答案即爲:\(C^m_n * d[n - m]\)

\(C^m_n = \frac{n!}{m!(n - m)!} = n! * (m!)^{p - 2} * ((n - m)!)^{p - 2},p = 1e9 +7\)

\(d[n] = (n - 1) (d[n - 1] + d[n - 2])\)

#include <iostream>
#include <cstdio>
using namespace std;
inline long long read() {
  long long x = 0; int f = 0; char c = getchar();
  while (c < '0' || c > '9') f |= c == '-', c = getchar();
  while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
  return f? -x : x;
}

const int mod = 1e9 + 7;
const int maxn = 1000006;
int T, n, m;
long long d[maxn], c[maxn];
inline long long pow(long long a, long long k) {//快速冪
  long long x = 1;
  while (k) {
    if (k & 1) x = x * a % mod;
    a = a * a % mod; k >>= 1;
  }
  return x;
}
int main() {
  T = read();
  c[0] = 1;//預處理
  for (int i = 1; i <= maxn; ++i) c[i] = c[i - 1] * i % mod;
  d[1] = 0; d[0] = 1;
  for (int i = 2; i <= maxn; ++i)
    d[i] = (d[i - 1] + d[i - 2]) % mod * (i - 1) % mod;
  while (T--) {
    n = read(); m = read();
    printf("%lld\n",d[n - m] % mod * 
      c[n] * pow(c[m], mod - 2) % mod * pow(c[n - m], mod - 2) % mod);
  }
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章