# 2021 Niuke summer multi school training camp 4 G, Product

## General idea of the topic

give n , k , D n,k,D n. K, D, the sequence you want to construct a i ≥ 0 , ∑ i = 1 n a i = D a_i\ge 0,\sum\limits_{i=1}^na_i = D ai ≥ 0,i=1 Σ n ai = D, for one of the sequences a a a his contribution is D ! ∏ i = 1 n ( a i + k ) ! \displaystyle\frac{D!}{\prod\limits_{i=1}^n(a_i+k)!} i=1∏n​(ai​+k)!D! Now, I want you to find out all the possibilities a a What is the sum of a sequence contributions?

n , k ≤ 50 , D ≤ 1 0 8 n,k\le50,D\le10^8 n,k≤50,D≤108

## Solution

Test point: dynamic programming + inclusion exclusion principle + significance of combination number

We first have to deduce the following formula, which can be seen as D D D balls divided into n n The number of possible schemes in n groups, then the total number of schemes is n D n^D nD, that is, each ball may be in each group.

∑ i = 1 n a i = D     ( a i ≥ 0 ) D ! ∗ ∏ i = 1 n 1 a i = n D \sum\limits_{i=1}^na_i = D \ \ \ (a_i\ge 0)\\D!*\prod\limits_{i=1}^n\displaystyle\frac{1}{a_i} = n^D i=1∑n​ai​=D   (ai​≥0)D!∗i=1∏n​ai​1​=nD

OK, let's go back to the formula given in the title. If we put a i + k a_i+k ai + k as a whole into the formula we just introduced above, we will get such a formula.

∑ i = 1 n a i = D + n k     ( a i ≥ 0 ) ( D + n k ) ! ∗ ∏ i = 1 n 1 a i = n D + n k \sum\limits_{i=1}^na_i = D+nk \ \ \ (a_i\ge 0)\\(D+nk)!*\prod\limits_{i=1}^n\displaystyle\frac{1}{a_i} = n^{D+nk} i=1∑n​ai​=D+nk   (ai​≥0)(D+nk)!∗i=1∏n​ai​1​=nD+nk

But it's easy to find that a problem is given by the title a i a_i ai} range is ≥ k \ge k ≥ k, but the range of our formula is ≥ 0 \ge 0 ≥ 0, which will lead to many illegal solutions when we directly calculate the answer, so we should consider removing all these illegal solutions and use the inclusion exclusion principle.

So we know we have n n Group n, then start 0 0 0 group of illegal answers minus yes 1 1 The solution of 1 set of illegal answers plus 2 2 Solutions of two sets of illegal answers ... ... ... until the inclusion exclusion coefficient is calculated, well, then the problem turns to how to solve it i i What about the number of solutions of group i illegal answers?

This solution is easier. Consider dynamic programming f [ i ] [ j ] f[i][j] f[i][j] stands for the former i i Group i currently has j j The number of solutions to be allocated for j balls.

We use O ( n ) O(n) The transfer of O(n) can find this f f f array.

f [ 0 ] [ 0 ] = 1 f i , j = ∑ s = 0 k − 1 f i − 1 , j − s ∗ C j s f = 1\\\\f_{i,j}=\sum\limits_{s=0}^{k-1}f_{i-1,j-s}*C_j^s f=1fi,j​=s=0∑k−1​fi−1,j−s​∗Cjs​

Next, the answer will be the following formula. From the front to the back, calculate the correction coefficient, inclusion exclusion coefficient, how many groups are illegal, how many balls are illegal, and calculate the number of combinations. Finally, calculate the number of schemes for the remaining groups and the remaining balls.

D ! ( D + n k ) ! ∑ i = 0 n ( − 1 ) i ∑ j = 0 i ∗ ( k − 1 ) f i , j ∗ C n i ∗ C D + n k j ∗ ( n − i ) D + n k − j \displaystyle\frac{D!}{(D+nk)!}\sum\limits_{i=0}^n(-1)^i\sum\limits_{j=0}^{i*(k-1)}f_{i,j}*C_n^i*C_{D+nk}^j*(n-i)^{D+nk-j} (D+nk)!D!​i=0∑n​(−1)ij=0∑i∗(k−1)​fi,j​∗Cni​∗CD+nkj​∗(n−i)D+nk−j

ll qpow(ll a, ll b) { ll ans = 1;	while (b) { if (b & 1)	ans *= a;		b >>= 1;		a *= a; }	return ans; }	ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int MOD = 998244353;
const int N = 55 + 7;
ll n, k, D;
int C[N * N][N * N];
int f[N][N * N];

inline int add(int a, int b) {
if (a + b >= MOD)	return a + b - MOD;
return a + b;
}

void init() {
for (int i = 0; i < N * N; ++i) {
C[i] = 1;
for (int j = 1; j <= i; ++j) {
C[i][j] = add(C[i - 1][j - 1], C[i - 1][j]);
}
}
f = 1;
for (int i = 0; i < n; ++i)
for (int j = 0; j <= i * (k - 1); ++j)
for (int s = 0; s <= k - 1; ++s)
f[i + 1][j + s] = add(f[i + 1][j + s], f[i][j] * C[j + s][s] % MOD);
}

inline int inv(int x) {
return qpow(x, MOD - 2, MOD);
}

int solve() {
init();

int res = 0;
for (int i = 0; i <= n; ++i) {
int jc = 1;
int sum = 0;
int pre = (i & 1) ? MOD - C[n][i] : C[n][i];

for (int j = 0; j <= i * (k - 1); ++j) {
int tmp = f[i][j] * qpow(n - i, D + n * k - j, MOD) % MOD * jc % MOD;
jc = jc * ((D + n * k - j) % MOD) % MOD * inv(j + 1) % MOD; // D is too big
}

res = add(res, sum * pre % MOD);
}

for (int i = D + 1; i <= D + n * k; ++i) {
res = res * inv(i) % MOD;
}
print(res);

return 1;
}


Posted on Fri, 12 Nov 2021 08:53:46 -0500 by pluginbaby