CF626F. Group Projects

发布时间 2023-08-03 10:54:47作者: xx019

我是傻逼。

哈哈,现在还想不到拆贡献,小丑一个。

人的输入顺序不重要,先排个序。这个 \(\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;
}