ARC207A Affinity for Artifacts

定义 \(sum = \sum_{i=1}^n a_i\).
定义 \(b = \{\ x\in \mathbb{N} \mid x \geq 0 且 x<n\}\).
题目显然要求我们将 \(a\)\(b\) 进行匹配,且有 \(t = \sum_{i=1}^n\min{a_i,b_{pos_i}}\),要求 \(x+t \geq sum\),求匹配方案数。
\(min\) 显然是难以处理的,考虑 \(trick:\)

将 a 和 b 放入一个数组中,从小到大排序,则容易定义状态。

这样就可以定义状态 \(f_{i,j,k}\) 表示前 \(i\) 个已经匹配了 \(j\) 对并且此时省了 \(k\) 的代价。
记前 \(i\) 个数中有 \(s\)\(a\),考虑转移:

  1. 若当前为 \(a\),若匹配,则有 \(f_{i,j,k} += f_{i-1,j-1,k} \cdot(i-s-j+1)\)
  2. 若当前为 \(b\),若匹配,则有 \(f_{i,j,k} += f_{i-1,j-1,k} \cdot (s-j+1)\)
  3. 若不匹配,则有 \(f_{i,j,k} += f_{i-1,j,k-vap_i}\).

答案为:

\[\sum_{i=\max{x,0}}^{n*n} f_{2n,n,i} \]

#include<bits/stdc++.h>
#define ll long long

using namespace std;

const int N = 105,mod = 998244353;

struct node{
	ll w,op;
	bool operator<(node b)const{
		return w<b.w;
	}
}b[N<<1];
ll n,x;
ll a[N];
ll f[2][N][N*N];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	cin>>n>>x;
	
	x=-x;
	for(int i=1;i<=n;i++)
		cin>>a[i],b[i].w=a[i],x+=a[i];
	
	for(int i=1;i<=n;i++)
		b[i+n].w=i-1,b[i+n].op=1;
	
	sort(b+1,b+(n<<1)+1);
	/*
	if(sum<=x){
		ll res=1;
		for(int i=1;i<=n;i++)
			res=res*i%mod;
		cout<<res<<"\n";
		return 0;
	}*/
	int res=0,cur=1;
	f[0][0][0]=1;
	for(int i=1;i<=(n<<1);i++,cur^=1){
		res+=b[i].op;
		for(int j=0;j<=min(i-res,res);j++){
			for(int k=0;k<=n*n;k++){
				f[cur][j][k]=0;
				if(k>=b[i].w)f[cur][j][k]+=f[cur^1][j][k-b[i].w];
				f[cur][j][k]%=mod;
				if(j && (b[i].op && i-res>=j))f[cur][j][k]+=f[cur^1][j-1][k]*(i-res-j+1)%mod;
				f[cur][j][k]%=mod;
				if(j && (!b[i].op && res>=j))f[cur][j][k]+=f[cur^1][j-1][k]*(res-j+1)%mod;
				f[cur][j][k]%=mod;
			}
		}
	}
	
	cur^=1;
	ll ans=0;
	for(int i=max(0ll,x);i<=n*n;i++)
		ans+=f[cur][n][i],ans%=mod/*,cout<<f[cur][n][i]<<" \n"[i==n*n]*/;
	cout<<ans<<"\n";
	return 0;
}
posted @ 2025-12-13 10:03  Harvey-zhuhy  阅读(4)  评论(0)    收藏  举报