codeforces 1188 C. Array Beauty (dp)
阿新 • • 發佈:2021-08-23
題目連結:https://codeforces.com/contest/1188/problem/C?mobile=true
美麗值的最大值就是將最大的數平分到 \((k-1)\) 個空位裡,即 \(\frac{x}{k-1}\),美麗值恰好為 \(v\) 的方案數不好算,考慮計算美麗值大於等於 \(v\) 的方案數
設 \(dp[i][j]\) 表示前 \(i\) 個數選了 \(j\) 個數的方案數,其中 \(i\) 必選,維護字首和 \(O(1)\) 轉移
時間複雜度為 \(O(nk \times \frac{x}{k-1}) = O(nx)\)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1010; const int M = 998244353; int n, k; int a[maxn], dp[maxn][maxn], sum[maxn][maxn], f[100010]; ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; } int main(){ n = read(), k = read(); int x = 0; for(int i = 1 ; i <= n ; ++i) a[i] = read(), x = max(x, a[i]); a[0] = -1000000007; sort(a + 1, a + 1 + n); for(int v = 1 ; v * (k-1) <= x ; ++v){ int pos = 0; dp[0][0] = 1; sum[0][0] = 1; for(int i = 1 ; i <= n ; ++i){ while(a[i] - a[pos+1] >= v && pos+1 <= i-1) { ++pos; } for(int j = 0 ; j <= k ; ++j){ if(j) dp[i][j] = sum[pos][j-1]; sum[i][j] = (sum[i-1][j] + dp[i][j]) % M; } f[v] = (f[v] + dp[i][k]) % M; } } for(int v = 1 ; v <= x / (k-1) ; ++v){ f[v] = ((f[v] - f[v+1]) % M + M) % M; } int ans = 0; for(int v = 1 ; v <= x / (k-1) ; ++v){ ans = (ans + 1ll * v * f[v] % M) % M; } printf("%d\n", ans); return 0; }