1. 程式人生 > 其它 >codeforces 1188 C. Array Beauty (dp)

codeforces 1188 C. Array Beauty (dp)

題目連結: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;
}