1042: [HAOI2008]硬币购物 DP+容斥原理

来源:互联网 发布:js正则密码区分大小写 编辑:程序博客网 时间:2024/06/06 04:23

果然高一抄代码抄多了,做了题和没做一样。我太弱啦。


我们考虑硬币没有限制的情况,令f[i]表示面值为i的方案数,则f[i]=sigma(f[i-c[k]],k∈[1,4])。
如果有限制的话,ans=没有限制的方案数-超过限制的方案数。
超过限制的方案数可以用容斥原理来做。

#include<iostream>#include<cstdio>#define MAXN 100000#define ll long long using namespace std;int c[5],d[5];ll ans,f[100005];int n;inline int read(){    int x=0;char ch=getchar();    while(ch<'0'||ch>'9')ch=getchar();    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x;}void dfs(int x,int k,int sum){    if (sum<0) return;    if (x==5)    {        if (k&1) ans-=f[sum];        else ans+=f[sum];        return;    }    dfs(x+1,k+1,sum-(d[x]+1)*c[x]);    dfs(x+1,k,sum);}int main(){    c[1]=read(); c[2]=read(); c[3]=read(); c[4]=read(); n=read();    f[0]=1;    for (int i=1;i<=4;i++)        for (int j=c[i];j<=MAXN;j++)            f[j]+=f[j-c[i]];    for (int i=1;i<=n;i++)    {        d[1]=read(); d[2]=read(); d[3]=read(); d[4]=read();         int s=read();        ans=0;        dfs(1,0,s);        printf("%lld\n",ans);    }    return 0;}
0 0
原创粉丝点击