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\),考虑转移:
- 若当前为 \(a\),若匹配,则有 \(f_{i,j,k} += f_{i-1,j-1,k} \cdot(i-s-j+1)\)
- 若当前为 \(b\),若匹配,则有 \(f_{i,j,k} += f_{i-1,j-1,k} \cdot (s-j+1)\)
- 若不匹配,则有 \(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;
}

浙公网安备 33010602011771号