容斥原理
一 定义
容斥原理就是说对于一些集合,要去求他们的并集。
from wiki
二 解题
优化的方向:如果已经知道物品的全部价值,进行多次查询,每一次的物品数目都是不一样的,背包的容量也是不一样的,此时如果直接去使用多重背包的一般解法(使用二进制转化为01背包问题或者使用单调队列进行优化)都会…T掉。所以要利用前面的状态就可以使用容斥原理进行优化
在初始的时候,我们将其作为完全背包进行处理,得到在物品数目不受限制的情况下的所有的可能数目。在利用容斥原理减去那些超过可行数目的解。就可以得到最终的数目
\\code
#include<iostream>
#define N 10010
#define ll long long
using namespace std;
ll f[N] = {1ll};
int cnt,c[5],d[5],n,s,value[N];
void Pre()
{
for(int i = 1;i <=4;i++)
for(int j = c[i];j <= N;j++)
f[j] += f[j - c[i]];
}
//完全背包的处理
inline int num(int id)
{
return c[id]*(d[id]+1);
}
//返回超过的体积
int main()
{
for(int i = 1;i <= 4;i++) scanf("%d",&c[i]);
Pre();
scanf("%d",&n);
while(n--)
{
for(int i = 1;i <= 4;i++) scanf("%d",&d[i]);
scanf("%d",&s);
ll ans = f[s];
for(int j = 1;j <= 15;j++)
{
int now = s,k = 0;
for(int z = j,Num = 1;z;z>>=1,Num++)
if(z&1) k ^= 1,now -= num(Num);
if(now >= 0) k? ans -= f[now]:ans += f[now];
}
//进行二进制枚举
printf("%lld\n",ans);
}
return 0;
}