Official

D - 積み上げるブロック / Stacking Blocks Editorial by physics0523


最初にブロックを置いた時に見える塔の数が必ず \(1\) になるので、 \(K>1\) である場合の答えは \(0\) です。

逆に、 \(K=1\) である場合はどのような順番でブロックを積み上げても構いません。
全部で \(S=\sum H\) 回の積み上げが必要になりますが、パターン数は以下のように求解できます。

  • \(i=1,2,\dots,N\) について順に以下を繰り返す。
    • どこに積むか決めていない \(S\) 回の操作のうち \(H_i\) 回を選択し、塔 \(i\) に積むと決める。なので、答えが \(C(S,i)\) 倍される。( \(C(n,r)\) は二項係数)
    • その後、 \(S\) から \(H_i\) 減算する。

本解法の時間計算量は \(O(\sum H)\) です。

実装例 (C++):

#include<bits/stdc++.h>
#include<atcoder/modint>

using namespace std;
using namespace atcoder;

using mint=modint1000000007;
using ll=long long;

mint nCr(ll n,ll r){
  mint res=1;
  for(ll i=1;i<=r;i++){
    res*=((mint)(n+1-i));
    res/=((mint)i);
  }
  return res;
}

int main(){
  ll N,K,s=0;
  cin >> N >> K;
  vector<ll> H(N);
  for(auto &nx : H){
    cin >> nx;
    s+=nx;
  }
  if(K>1){cout << "0\n"; return 0;}
  mint res=1;
  for(auto &nx : H){
    res*=nCr(s,nx);
    s-=nx;
  }
  cout << res.val() << "\n";
  return 0;
}