AtCoder Beginner Contest 226 F
阿新 • • 發佈:2021-11-09
題意:題意省~
sol.考慮 你每一個排列的分數,是若干個迴圈長度的lcm
然後只要計數方案就好了
考慮 長度\(a_i\)的環有\(b_i\)個
那麼這個環貢獻的方案數就是
\[\frac{C^{a_i * b_i}_{rest}}{(b_i - 1)} * 分配的方案數 \]#include<bits/stdc++.h> #define MAXN 55 typedef long long ll; const ll mod = 998244353; using namespace std; int n,k; ll C[MAXN][MAXN],ans = 1; ll jc[MAXN],inv[MAXN]; ll mul(ll x , ll y){return x * y % mod;} ll poww(ll x , int y){ ll zz = 1; while(y){ if(y & 1)zz = zz * x % mod; x = x * x % mod; y = y >> 1; } return zz; } vector<int>q; ll gcd(ll x , ll y){ if(!y)return x; return gcd(y , x % y); } ll lcm(ll x , ll y){ ll zz = gcd(x , y);x /= zz; return x * y; } map<int , int>mp; void dfs(int now , int pre){ if(!now){ ll LCM = 1 , zz = 1;mp.clear(); for(int i = 0 ; i < q.size() ; i++)LCM = lcm(LCM , q[i]); for(int i = 0 ; i < q.size() ; i++)mp[q[i]]++ , zz = zz * jc[q[i] - 1] % mod; now = n; for(auto it : mp){ zz = zz * C[now][(it.first) * (it.second)] % mod; for(int i = 1 ; i <= it.second ; i++)zz = zz * C[i * it.first][it.first] % mod; zz = zz * inv[it.second] % mod; now -= it.first * it.second; } ans = (ans + zz * poww(LCM , zz) % mod) % mod; return; } for(int i = pre ; i <= now ; i++){ q.push_back(i); dfs(now - i , i); q.pop_back(); } } int main(){ jc[0] = 1;for(int i = 1 ; i <= 50 ; i++)jc[i] = jc[i - 1] * i % mod; for(int i = 0 ; i <= 50 ; i++)inv[i] = poww(jc[i] , mod - 2); for(int i = 0 ; i <= 50 ; i++) for(int i = 0 ; i <= 50 ; i++){ C[i][0] = 1; for(int j = 1 ; j <= i ; j++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; } scanf("%d%d" , &n , &k); dfs(n , 1); cout<<ans<<endl; }