AtCoder 2000 [AGC002F] Leftmost Ball(dp+组合数)
problem
洛谷鏈接
solution
顯然,合法序列的狀態要求任何一個前綴的白色球數≥\ge≥已出現的不同顏色數。
所以可以將球分成白色球和有顏色球兩類球分開放。
其次,有顏色球一類重要的是有顏色球第一個放的位置,因為這會影響到前綴顏色數以及前綴白色球數的限制。
再者,不同顏色間是等價的,不妨先不區分顏色,只考慮每組個數,最后上顏色時再乘以 n!n!n! 。
考慮確定當前第一個空位放什么類球,設 fi,j:f_{i,j}:fi,j?: 放了 iii 個白球,jjj 組顏色球的方案數。
-
放白球。fi,j←+fi?1,jf_{i,j}\leftarrow^+f_{i-1,j}fi,j?←+fi?1,j?。
-
放第一個有顏色球。fi,j←+(nk?(j?1)(k?1)?i?1k?2)fi,j?1f_{i,j}\leftarrow^+\binom{nk-(j-1)(k-1)-i-1}{k-2}f_{i,j-1}fi,j?←+(k?2nk?(j?1)(k?1)?i?1?)fi,j?1?。
簡單解釋一下這個組合數系數怎么來的。
總球數 nknknk,大前提下的分類 nnn 個白球,n(k?1)n(k-1)n(k?1) 個有顏色球。
放了 iii 個白球,放了 j?1j-1j?1 組有顏色球,共 (j?1)(k?1)(j-1)(k-1)(j?1)(k?1) 個。
當前空位(前面都放滿了)強制是第 jjj 組顏色球的第一個。
每組球拿了一個做白球,固定了第一個位置,剩下 k?2k-2k?2 個球的位置就是隨意選擇的了。
code
#include <bits/stdc++.h> using namespace std; #define int long long #define mod 1000000007 #define maxn 2505 int n, k; int inv[maxn * maxn], fac[maxn * maxn]; int f[maxn][maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans; }int C( int n, int m ) { if( n < m or m < 0 ) return 0;else return fac[n] * inv[m] % mod * inv[n - m] % mod; }signed main() {scanf( "%lld %lld", &n, &k );if( k == 1 ) return ! printf( "1\n" );fac[0] = inv[0] = 1;for( int i = 1;i <= n * k;i ++ ) fac[i] = fac[i - 1] * i % mod;inv[n * k] = qkpow( fac[n * k], mod - 2 );for( int i = n * k - 1;i;i -- ) inv[i] = inv[i + 1] * ( i + 1 ) % mod;f[0][0] = 1;for( int i = 1;i <= n;i ++ )for( int j = 0;j <= i;j ++ ) {( f[i][j] += f[i - 1][j] ) %= mod;if( j ) ( f[i][j] += C( n * k - i - ( j - 1 ) * ( k - 1 ) - 1, k - 2 ) * f[i][j - 1] % mod ) %= mod;}printf( "%lld\n", f[n][n] * fac[n] % mod );return 0; }總結
以上是生活随笔為你收集整理的AtCoder 2000 [AGC002F] Leftmost Ball(dp+组合数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces1477D Nezz
- 下一篇: 中科大研究生信息平台抢课脚本低级版本