Loading

洛谷1450-HAOI硬币购物题解-容斥原理

1450-HAOI硬币购物

考虑不记d[i]限制的情况,其实就是裸的完全背包。

\[dp[i]=∑dp[i-k*c[i]] \]

完全背包的优化:

\[dp[i]+=dp[i-c[i]] \]

对于四种硬币跑四轮即可。时间复杂度O(4e5)

然后考虑容斥定理,dp[i]表示凑到i元的全部可能情况,答案要在dp[s]的基础上减去所有不符合要求的情况。

如果有一种硬币超出了要求,相当于他花费了d[i]+1个硬币然后再凑到s元,那么其实就是dp[s-(d[i]+1)*c[i]]

对多种硬币同时超出要求的情况dp[s-(d[i]+1)*c[i]-(d[j]+1)*c[i]...]

这几种情况是有重复的,满足容斥原理,利用二进制的方法辅助计算。代码如下:

signed main(){
    ios;fre();
    dp[0]=1;
    cin>>c[1]>>c[2]>>c[3]>>c[4]>>n;
    for(int i=1;i<=4;i++){
        for(int j=c[i];j<=1e5;j++){
            dp[j]+=dp[j-c[i]];
        }
    }
    while(n--){
        cin>>d[1]>>d[2]>>d[3]>>d[4]>>s;
        ll ans=0;
        for(int i=0;i<16;i++){
            int cnt=0;ll now=0;
            for(int j=1;j<=4;j++){
                if(i&(1<<(j-1))) now+=(d[j]+1)*c[j],cnt++;
            }
            if(s-now>=0) ans+=(cnt%2*2-1)*dp[s-now];
        }
        cout<<-ans<<endl;
    }
    return 0;
}
posted @ 2021-04-02 22:27  14long  阅读(123)  评论(0)    收藏  举报