题解 P1450 【[HAOI2008]硬币购物】
本题想到多重背包还是很容易的(什么?不知道多重背包?)
但是,另一题解已经将时间安排计算地明明白白
所以想到完全背包(多重背包跟01背包似乎区别不大)
可以先预处理完全背包的情况,然后瞎搞容斥原理
不懂容斥原理的看这里:传送门
想到完全背包和容斥原理后,剩下的就只是打表一些简单的实现了
上代码
#include<bits/stdc++.h>
using namespace std;
long long c[5],d[5],dp[100010],tot,s;
long long Q(long long x)//便于打表
{
return c[x]*(d[x]+1);
}
int main()
{
for(int i=1;i<=4;i++)
{
cin>>c[i];
}
cin>>tot;
dp[0]=1;//初始化,之后预处理
for(int i=1;i<=4;i++)
{
for(int j=c[i];j<=100001;j++)
{
dp[j]+=dp[j-c[i]];
}
}
for(int js=1;js<=tot;js++)
{
for(int i=1;i<=4;i++)
{
cin>>d[i];
}
cin>>s;
long long ans=dp[s];//初始,之后容斥原理代码
if(s>=Q(1))
ans-=dp[s-Q(1)];
if(s>=Q(2))
ans-=dp[s-Q(2)];
if(s>=Q(3))
ans-=dp[s-Q(3)];
if(s>=Q(4))
ans-=dp[s-Q(4)];
if(s>=Q(1)+Q(2))
ans+=dp[s-Q(1)-Q(2)];
if(s>=Q(1)+Q(3))
ans+=dp[s-Q(1)-Q(3)];
if(s>=Q(1)+Q(4))
ans+=dp[s-Q(1)-Q(4)];
if(s>=Q(2)+Q(3))
ans+=dp[s-Q(2)-Q(3)];
if(s>=Q(2)+Q(4))
ans+=dp[s-Q(2)-Q(4)];
if(s>=Q(3)+Q(4))
ans+=dp[s-Q(3)-Q(4)];
if(s>=Q(1)+Q(2)+Q(3))
ans-=dp[s-Q(1)-Q(2)-Q(3)];
if(s>=Q(1)+Q(2)+Q(4))
ans-=dp[s-Q(1)-Q(2)-Q(4)];
if(s>=Q(1)+Q(3)+Q(4))
ans-=dp[s-Q(1)-Q(3)-Q(4)];
if(s>=Q(2)+Q(3)+Q(4))
ans-=dp[s-Q(2)-Q(3)-Q(4)];
if(s>=Q(1)+Q(2)+Q(3)+Q(4))
ans+=dp[s-Q(1)-Q(2)-Q(3)-Q(4)];//个人认为这个表打得相当美观~
cout<<ans<<endl;
}
}