题解:P5131 荷取融合
Description
定义一次操作为在
Analysis
先来观察操作次数。在
接下来来看总收益。记
- 最后一个不是
j ,即只能从前j-1 个选。和为dp_{i,j-1} 。 - 最后一个是
j ,即前i-1 个选自1\sim j ,其乘积dp_{i-1,j} 再乘上本次的a_j ,即为和。
故
但由于
时间复杂度
Code
#include"bits/stdc++.h"
#define int long long
using namespace std;
const int N = 2e5 + 5, mod = 19260817;
int n, k, a[N];
int dp[2][N];
int fac[N], inv[N];
int fpow(int a, int b) {
int re = 1;
while (b) {
if (b & 1)
re = re * a % mod;
a = a * a % mod;
b >>= 1;
}
return re;
}
void init() {
fac[0] = 1;
for (int i = 1; i < N; i++)
fac[i] = fac[i - 1] * i % mod;
inv[N - 1] = fpow(fac[N - 1], mod - 2);
for (int i = N - 2; ~i; i--)
inv[i] = inv[i + 1] * (i + 1) % mod;
}
int C(int n, int m) {
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
signed main() {
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
init();
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
dp[1][i] = 1;
int cur = 1;
for (int i = 1; i <= k; i++) {
cur ^= 1;
for (int j = 1; j <= n; j++)
dp[cur][j] = (dp[cur][j - 1] + a[j] * dp[cur ^ 1][j]) % mod;
}
cout << fpow(C(n + k - 1, k), mod - 2) * dp[cur][n] % mod;
return 0;
}