2023牛客暑期多校训练营6 - B-Distance

 思路:若要能操作,首先S,T子集长度相同,其次要操作次数最少,必定是小的跟小的操作,大的跟大的操作,也就是说对S,T按大小排序后,S,T中下标相同的数进行操作是最优的。现在就考虑a中第i位对于b中第j位的最优贡献次数,也就是S中大于等于a_{i}的数量必须要等于T中大于等于b_{j}的数目,小于也是同理,才能保证他们的相对位置一致。

所以a中第i位对b中第j位的贡献就是f_{ij}=\sum_{k=0}^{min(i,j)}C_{i}^{k}C_{j}^{k},这里用一个范德蒙卷积公式就能转化成f_{ij}=\sum_{k=0}^{min(i,j)}C_{i}^{k}C_{j}^{k}=C_{i+j}^{i}就能计算。具体证明去查

#include
using namespace std;
#define ll long long 
const ll mod=998244353;
ll c[4010][4010];
ll a[4010][4010];
ll s[2010];
ll t[2010];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin >> n;

	for (int i = 1; i <= n; i++)
	{
		cin >> s[i];
	}
	for (int j = 1; j <= n; j++)
	{
		cin >> t[j];
	}
	sort(s + 1, s + n + 1);
	sort(t + 1, t + n + 1);
	//组合数预处理 
	for (int i = 0; i <= 2 * n; i++)
	{
		for (int j = 0; j <= i; j++)
		{
			if (!j)c[i][j] = 1;
			else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
		}
	}
	//范德蒙卷积结果,预处理好 
	for (int i = 0; i <= n; i++)
	{
		for (int j = 0; j <= i; j++)
		{
			a[i][j] = a[j][i] = c[i + j][j];
		}
	}
	ll ans = 0;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			ans = (ans + abs(s[i]-t[j])*(a[i - 1][j - 1])%mod * (a[n - i][n - j]) %mod) % mod;
		}
	}
	ans = (ans % mod + mod) % mod;
	cout << ans << endl;
	return 0;
}

你可能感兴趣的:(牛客2023暑假多校,数论,算法)