Codeforces Round #309 (Div. 1) A. Kyoya and Colored Balls
Codeforces Round #309 (Div. 1)に参加しました。結果はAB解けて個人的には満足だったんですがレートは多少落ちました(得点dynamic形式は強い人にかなり有利なルールな気がするのでもうちょっと工夫してほしいなぁと思います)。解いてて結構楽しかったのであんまり気にしてないですが。
解法
後ろから考えていきます。例えば問題文の2つ目のサンプルを見てみましょう。
問題の制約から,4が一番後ろに来ることは確定しています。残りの3つの4は好きな場所に配置してよいですが,この配置の仕方はどうなるかというと,1,2,3のボールが6個あって残りの4はこれらのボールの間に入れていくと考えることができるので
通りあります。
同様に考えて,次は3のボールを配置することを考えます。3は1,2,3のボールの中で一番最後に一つボールが来ることは確定していて,残りの2つの3のボールの配置の仕方が何通りあるかを考えます。これは1,2のボール3つの中に2つのボールを入れていくと考えることができるので通りあります。以下同様です。
何故か制約がゆるいのででも大丈夫です。
const int MAXN = 1011; const ll MOD = 1e9+7; int a[MAXN]; ll fact[MAXN]; // extgcd ll extgcd(ll a, ll b, ll& x, ll& y) { ll d = a; if (b != 0) { d = extgcd(b, a % b, y, x); y -= (a / b) * x; } else { x = 1; y = 0; } return d; } // mod_inverse ll mod_inverse(ll a, ll m = MOD) { ll x, y; extgcd(a, m, x, y); return (m+x%m) % m; } ll nCr(int n, int r) { return (((fact[n] * mod_inverse(fact[r])) % MOD) * mod_inverse(fact[n-r])) % MOD; } int main() { cin.tie(0); ios::sync_with_stdio(false); int n; cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; } fact[0] = 1; for (int i = 1; i < MAXN; i++) { fact[i] = fact[i-1] * i; fact[i] %= MOD; } ll ans = 1; for (int k = n-1; k > 0; k--) { int sum = 0; for (int i = 0; i < k; i++) { sum += a[i]; } ans *= nCr(sum+a[k]-1, a[k]-1); ans %= MOD; } cout << ans << endl; return 0; }