牛客练习赛64 D 宝石装箱(容斥+背包DP)

题目链接
牛客练习赛64 D 宝石装箱(容斥+背包DP)_第1张图片
思路:因为第 i 个箱子 至少放了 j 个不合法宝石 是用前面一个状态(dp[j-1]) 推出所以在枚举放不合法宝石的时候逆序枚举就可以实现内存优化,然后合法宝石的排列是 (n-i)!(n−i)! , 不合法宝石的排列是 dp[i]*a[i]dp[i]∗a[i],因为是至少放了 x 个不合法宝石,所以肯定存在重复的方案,就需要进行容斥
偶数加,奇数减!

#include 
using namespace std;
typedef long long ll;
const int maxn=8e3+5;
const int mod=998244353;
ll dp[maxn],f[maxn],a[maxn],ans;
int main()
{
    int n,t;
    scanf("%d",&n);
    dp[0]=f[0]=1;
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&t);
        a[t]++;
        f[i]=f[i-1]*i%mod;
    }
    for(int i=1;i<=n;++i)
    for(int j=n;j>=1;--j)
    dp[j]=(dp[j]+dp[j-1]*a[i])%mod;
    for(int i=0,j=1;i<=n;++i,j*=-1) (ans+=1ll*j*dp[i]*f[n-i])%=mod;
     printf("%lld\n",(ans+mod)%mod);
}

你可能感兴趣的:(背包DP)