我是傻逼。
哈哈,现在还想不到拆贡献,小丑一个。
人的输入顺序不重要,先排个序。这个 \(\text{max}-\text{min}\) 可以看作两两之差的和。定义 \(f_{i,j,k}\) 表示考虑前 \(i\) 个人,有 \(j\) 个组没有确定最大值,目前不和谐度之和为 \(k\) 的方案数,转移分四种情况:
-
单独构成完整的一组;
-
成为新的一组的最小值;
-
成为一组的中间值;
-
成为一组的最大值;
这是 \(\mathcal{O}(n^2k)\) 的。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
inline int read(){
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int a[205],f[205][205][1005];
signed main(){
int n=read(),m=read();
for(int i=1;i<=n;i++)a[i]=read();
sort(a+1,a+n+1);f[0][0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=n;j++){
for(int k=0;k<=m;k++){
if(k>=(a[i]-a[i-1])*j)f[i][j][k]=(f[i][j][k]+f[i-1][j][k-(a[i]-a[i-1])*j])%mod;
if(k>=(a[i]-a[i-1])*j)f[i][j][k]=(f[i][j][k]+1ll*f[i-1][j][k-(a[i]-a[i-1])*j]*j%mod)%mod;
if(j-1>=0&&k>=(a[i]-a[i-1])*(j-1))f[i][j][k]=(f[i][j][k]+1ll*f[i-1][j-1][k-(a[i]-a[i-1])*(j-1)])%mod;
if(j+1<=n&&k>=(a[i]-a[i-1])*(j+1))f[i][j][k]=(f[i][j][k]+1ll*f[i-1][j+1][k-(a[i]-a[i-1])*(j+1)]*(j+1)%mod)%mod;
}
}
}
int ans=0;
for(int i=0;i<=m;i++)ans=(ans+f[n][0][i])%mod;
printf("%d\n",ans);
return 0;
}