题解:AT_arc207_a [ARC207A] Affinity for Artifacts
threediamond · · 题解
题目可以转化为求合法的
把上面的式子变换成
这样我们就能发现当
所以问题就可以转化为求满足
对于这种问题,我们可以考虑将两个序列中的数放进一个序列
这样的一个序列就很好处理了,考虑 dp。设当前考虑到前
接下来考虑状态转移。分两种情况:
- 第
i 个点是1 序列的。有dp_{i,j,s}=dp_{i-1,j-1,s}+dp_{i-1,j,s-b_i}\times (R-L+j+1) ,代表当前点是否匹配。 - 第
i 个点是2 序列的。有dp_{i,j,s}=dp_{i-1,j,s}+dp_{i-1,j+1,s-b_i}\times (j+1) 。
最后的答案就是
#include<bits/stdc++.h>
using namespace std;
const long long mod=998244353;
long long n,m,a[110],idx;
long long dp[210][210][5010],ans;
struct node{
long long num,op;
}b[210];
bool cmp(node x,node y){
return x.num>y.num;
}
int main(){
scanf("%lld%lld",&n,&m);
long long sum=0;
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]),sum+=a[i],b[++idx].num=a[i],b[idx].op=1;
sum=sum-m;
if(sum<0){
ans=1;
for(int i=1;i<=n;i++)
ans*=i,ans%=mod;
printf("%lld",ans);
return 0;
}
if(sum>n*(n-1)/2){
printf("0");
return 0;
}
for(int i=1;i<=n;i++)b[++idx].num=i-1,b[idx].op=2;
sort(b+1,b+2*n+1,cmp);
long long L=0,R=0;
dp[0][0][0]=1;
for(int i=1;i<=2*n;i++){
if(b[i].op==1)L++;
else R++;
for(int j=0;j<=L;j++){
long long k=R-L+j;
for(int s=0;s<=n*(n-1)/2;s++){
if(b[i].op==1){
if(j>0)dp[i][j][s]+=dp[i-1][j-1][s],dp[i][j][s]%=mod;
if(s>=b[i].num)dp[i][j][s]+=dp[i-1][j][s-b[i].num]*(k+1),dp[i][j][s]%=mod;
}
else{
dp[i][j][s]+=dp[i-1][j][s],dp[i][j][s]%=mod;
if(s>=b[i].num)dp[i][j][s]+=dp[i-1][j+1][s-b[i].num]*(j+1),dp[i][j][s]%=mod;
}
}
}
}
for(int i=sum;i<=n*(n-1)/2;i++){
ans+=dp[2*n][0][i],ans%=mod;
}
printf("%lld",ans);
return 0;
}