应该算是我做的正儿八经的容斥的第一道题吧。
直接做时间复杂度是(O(4nS))的,显然不能接受。注意到这题只有(4)个物品,考虑容斥。
容斥模型:
- 元素:每一种方案
- 全集:所有组合总和为(n)的方案
- 属性:对每个物品购买的数量限制
这道题显然是对每个属性求交集,于是转化成了全集-补集的并集模型,由于只有(4)个物品,所以可以直接预处理+暴力枚举,时间复杂度(O(4max(S),2^4n))
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=100000;
int c[5],n,d[5],s;
LL f[N+9];
void init()
{
for (int i=1;i<=4;i++)
scanf("%d",&c[i]);
scanf("%d",&n);
f[0]=1;
for (int i=1;i<=4;i++)
for (int j=c[i];j<=N;j++)
f[j]+=f[j-c[i]];
}
void work()
{
while(n--)
{
for (int i=1;i<=4;i++)
scanf("%d",&d[i]);
scanf("%d",&s);
LL ans=0;
for (int i=1;i<16;i++)
{
int cnt=0;LL m=s;
for (int j=1;j<=4;j++)
if(i&(1<<j-1))
cnt++,m-=1ll*(d[j]+1)*c[j];
if(m>=0) ans+=(cnt&1)?f[m]:-f[m];
}
printf("%lld
",f[s]-ans);
}
}
int main()
{
init();
work();
return 0;
}