Character Encoding(組合數學相關)
阿新 • • 發佈:2018-12-15
題目大意:
給你 n,m,k,讓你求 方程的解的個數。
題解:
如果 的限制只是 則通過k個球,m個箱子的插板法很容易得出解的個數為
之後在那麼多的解的個數中,還要排除所有 的解
先排除有一個 的情況,其個數為
排除之後,有發現多排除了有兩個 的情況,於是又要把它加回來,個數為
而在加回來之後,有發現多加了有三個 的情況,於是又要把他們減掉
其中,例如, 表示有 2列n個球在m個箱子中,而表示減去2*n個球之後,剩下的球在m個箱子中放的方案數
總結就是運用組合數的容斥原理,最終結果為
AC程式碼:
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> using namespace std; typedef long long ll; const ll MOD = 998244353; const ll N = 300010; ll jc[N]; void init() { ll i; jc[0] = 1; for(i=1;i<N;i++) jc[i] = jc[i-1]*i%MOD; } ll m_pow(ll n,ll p) { if(p == 0) return 1; if(p&1) return m_pow(n*n%MOD,p>>1)*n%MOD; else return m_pow(n*n%MOD,p>>1)%MOD; } ll inv(ll n) { return m_pow(n,MOD-2); } ll C(ll a,ll b) { if(a < b) return 0; return jc[a]*inv(jc[b]*jc[a-b]%MOD)%MOD; } int main() { init(); int T; scanf("%d",&T); while(T--) { int n,m,k; ll ans=0; ll i; scanf("%d%d%d",&n,&m,&k); if(k == 0) { printf("1\n"); continue; } if(k < n) { ans = C(m+k-1,m-1); printf("%lld\n",ans); continue; } if(k > m*(n-1)) { printf("0\n"); continue; } ans = C(m+k-1,m-1); for(i=1;i<=m;i++) { if(i&1) ans -= C(m,i)*C(m+k-1-i*n,m-1)%MOD; else ans += C(m,i)*C(m+k-1-i*n,m-1)%MOD; ans = (ans+MOD)%MOD; } printf("%lld\n",ans); } return 0; }