链接
https://codeforces.com/contest/1188/problem/C
题解
这题感觉不是那么直接
首先排序
那么最小的
∣
b
i
−
b
i
−
1
∣
|b_i-b_{i-1}|
∣bi−bi−1∣肯定就出现在相邻的两个数
然后可以设计
d
p
dp
dp:
f
i
j
k
f_{ijk}
fijk表示前
i
i
i个数选择了
j
j
j个,最小间距为
k
k
k
这样设计状态的话,转移的时候就会遇到麻烦,比较复杂
看了题解之后,发现题解做了这样一件事情:枚举最小间距
x
x
x,然后统计有多少子序列的美丽度是大于等于
x
x
x的,最后对
x
=
1
x=1
x=1到
m
a
x
(
a
i
)
k
−
1
max(a_i)\over k-1
k−1max(ai)求和
这个确实是妙啊,一个序列的美丽度如果是
t
t
t,那么显然它会被算到
t
t
t次,太妙了
那如果我改成美丽度等于
∣
b
i
−
b
i
−
1
∣
2
|b_i-b_{i-1}|^2
∣bi−bi−1∣2,是不是我每次算完了乘上一个奇数就行了?有意思(一道题又诞生了)
代码
#include<bits/stdc++.h>
#define maxn 1010
#define linf (1ll<<60)
#define iinf 0x3f3f3f3f
#define eps 1e-8
#define cl(x) memset(x,0,sizeof(x))
#define mod 998244353ll
using namespace std;
typedef long long ll;
ll read(ll x=0)
{
int c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
ll f[maxn], s[maxn], N, a[maxn], K;
int main()
{
ll i, j, x, p, ans(0);
ios::sync_with_stdio(false);
N=read(), K=read();
for(i=1;i<=N;i++)a[i]=read();
a[0]=-linf;
sort(a+1,a+N+1);
for(x=1;x<=a[N]/(K-1);x++)
{
for(j=1;j<=N;j++)f[j]=1, s[j]=j;
for(i=2;i<=K;i++)
{
p=N;
for(j=N;j>=i;j--)
{
while(p and a[j]-a[p]<x)p--;
f[j]=s[p];
}
while(j)f[j--]=0;
for(j=1;j<=N;j++)s[j]=(s[j-1]+f[j])%mod;
}
ans=(ans+s[N])%mod;
}
cout<<ans;
return 0;
}