题解
转载自官方题解
设 (g(x)) 表示选定 (x) 个箱子装不合法的宝石的方案数。
设 (f(x)=x!) 表示选 (x) 个箱子任意装宝石的方案数。
那么 (g(x)*f(n-x)) 表示至少 (x) 个箱子装了不合法宝石的方案数。
根据容斥原理,答案为 (sum_{i=0}^n(-1)^i*g(i)*f(n-i))。
设 (a_i) 表示不可以装入 (i) 箱子的宝石的数量,因为一个宝石对应一个箱子,每个箱子不可以装的宝石不会有重叠。
初始时,(g(0)=1,g(i)=0)。
然后相当于每次加入一个物品,当加到 (i) 号箱子,有 (g(k)=g(k-1)*a_i),就可以通过背包求出 (g) 了。
复杂度 (O(n^2))。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=8010;
const int mod=998244353;
int n,a[N];
LL fac[N]={1},f[N]={1};
int main(){
scanf("%d",&n);
for(int i=1,x;i<=n;i++){
scanf("%d",&x),a[x]++;
fac[i]=fac[i-1]*i%mod;
}
for(int i=1;i<=n;i++)
for(int j=n;j>=1;j--)
(f[j]+=f[j-1]*a[i])%=mod;
LL ans=0;
for(int i=0,j=1;i<=n;i++,j*=-1) (ans+=1ll*j*f[i]*fac[n-i])%=mod;
printf("%lld
",(ans+mod)%mod);
return 0;
}