公式

D - 植木の配置 / Arrangement of Trees 解説 by kyopro_friends


\(N\) 個の区画から、隣り合わないように \(K\) 個を選ぶ」は、選ぶ区画を左右に半区画ずつふくらませることで「 \(N+1\) 個の区画に \(K\) 個のドミノを置く」と等価になります。

図

これは「\(K\) 個のドミノと \(N+1-2K\) 個の正方形の合計 \(N+1-K\) 個を並べる」と等価なので、「\(N+1-K\) 箇所のうちドミノを置く \(K\) 箇所を選ぶ」と思うことで \(\binom{N+1-K}{K}=\frac{(N+1-K)!}{K!(N+1-2K)!}\) 通りとなることがわかります。

分子と分母をそれぞれ \(\bmod 10^9+7\) で計算し、最後に除算を行うことで、 \(O(N + \log \mathrm{MOD})\) でこの問題を解くことができます。(制約の範囲で分母は \(0\) になりません)

実装例 (C++)

#include<bits/stdc++.h>
#include<atcoder/modint>
using namespace std;
using modint = atcoder::modint1000000007;

modint fact(int n){
  modint crr = 1;
  for(int i=1; i<=n; i++){
    crr *= i;
  }
  return crr;
}

int main(){
  int n, k;
  cin >> n >> k;

  if(n+1-k-k < 0){
    cout << 0 << endl;
  }else{
    modint nume = fact(n+1-k);
    modint deno = fact(k) * fact(n+1-k-k);
    cout << (nume/deno).val() << endl;
  }
}

実装例 (Python)

MOD = 10**9 + 7
N, K = map(int, input().split())

def fact(n):
  crr = 1
  for i in range(1, n+1):
    crr = crr * i % MOD
  return crr

if N+1-K-K < 0:
  print(0)
else:
  nume = fact(N+1-K)
  deno = fact(K) * fact(N+1-K-K)
  print(nume * pow(deno, -1, MOD) % MOD)

投稿日時:
最終更新: