luogu p4141 消失之物(背包dp+容斥原理)

题目传送门

昨天晚上学长讲了这题,说是什么线段树分治,然后觉得不可做,但那还不是正解,然后感觉好像好难的样子。

由于什么鬼畜的分治不好打,然后想了一下$O(nm)$的做法,想了好长时间觉得这题好像很像大力容斥。然后疯狂yy

正经题解:

$O(n^2m)$的解法很好想,就是一个个枚举,但是显然时间吃不消,在观察题目,根据zzh学长的根据题目核心性质猜测法(雾

我们可以考虑容斥因为他题目的限制条件就是每次去掉一个物体,那么就可以先$O(nm)$处理出没有限制条件的总方案数,然后单步容斥,枚举每次去掉的物品,然后把那种物品的方案数剪掉即可

时间复杂度$O(nm)$

最后记得多取模。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #include<vector>
 8 using namespace std;
 9 const int N=4e3+10;
10 int v[N],f[N],g[N];
11 int n,m;
12 int main(){
13     scanf("%d%d",&n,&m);
14     for(int i=1;i<=n;i++) scanf("%d",&v[i]);
15     f[0]=1;
16     for(int i=1;i<=n;i++) for(int j=m;j>=v[i];j--) (f[j]+=f[j-v[i]])%=10;
17     for(int i=1;i<=n;i++){
18         for(int j=0;j<=m;j++) g[j]=f[j]%10;
19         for(int j=v[i];j<=m;j++){
20             g[j]=((g[j]-g[j-v[i]])%10+10)%10;
21         }
22         for(int i=1;i<=m;i++) printf("%d",g[i]);
23         puts("");
24     }
25 }
View Code
原文地址:https://www.cnblogs.com/leom10/p/11281486.html