题意很好转化,就是求该序列里所有子序列的完美度之和
我首先想到的是二维dp做,但是我太菜了,不会搞最小值。
那先排个序。
我们可以发现完美度之和最多是序列中最大值/(k-1)
于是我们可以在最外面一层循环枚举完美度,对每个完美度所对应的方案数进行dp。
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示前
i
i
i个数选
j
j
j个,很容易设计方程:
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
]
+
f
[
t
e
m
p
]
[
j
−
1
]
f[i][j]=f[i-1][j]+f[temp][j-1]
f[i][j]=f[i−1][j]+f[temp][j−1]
此处temp为最大可以满足
a
[
i
]
−
a
[
t
e
m
p
]
>
=
a[i]-a[temp]>=
a[i]−a[temp]>=当前完美度的下标
dp复杂度为O(nk),总复杂度约为O(n*maxn),好像卡的有点紧(也可能是我太菜了自带大常数),但能过。
//love
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int NUM=1005;
const int MOD=998244353;
int n,k,temp,tempp,ans;
int a[NUM],f[NUM][NUM],g[NUM][NUM];
inline int min(int x,int y){return x>y ? y : x;}
signed main()
{
freopen("love.in","r",stdin);
freopen("love.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;++i)
cin>>a[i];
sort(a+1,a+1+n);
tempp=(a[n]-a[1])/(k-1);
for(int tt=1;tt<=tempp;++tt)
{
temp=0;
f[0][0]=1;
for(int i=1;i<=n;++i)
{
f[i][0]=f[i-1][0]%MOD;
while(a[i]-a[temp+1]>=tt)
++temp;
int mintemp=min(i,k);
for(int j=1;j<=mintemp;++j)
f[i][j]=(f[i-1][j]+f[temp][j-1])%MOD;
}
ans=(ans+f[n][k])%MOD;
}
cout<<ans;
return 0;
}