NC19974 硬币购物(dp+容斥)

显然不能暴力求解,进一步发现性质,我们要求的是每一个都满足限制。

正难则反,用总方案数-至少一种不满足的方案数

后面那个可以看得出来和容斥定理有关,因此考虑容斥,某个物品不满足,说明他至少取了d[i]+1个,其他随意,因此我们就求出了解答

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e5+10;
const int mod=1e9+7;
ll c[N],d[N];
ll f[N];
void solve(){
    int i;
    for(i=1;i<=4;i++){
        cin>>d[i];
    }
    int s;
    cin>>s;
    ll ans=f[s];
    for(i=1;i<(1<<4);i++){
        int tmp=0;
        int cnt=0;
        for(int j=0;j<4;j++){
            if(i>>j&1){
                tmp+=c[j+1]*(d[j+1]+1);
                cnt^=1;
            }
        }
        if(s<tmp)
            continue;
        ans=cnt?ans-f[s-tmp]:ans+f[s-tmp];
    }
    cout<<ans<<endl;
}
int main(){
    ios::sync_with_stdio(false);
    int i;
    for(i=1;i<=4;i++)
        cin>>c[i];
    int t;
    cin>>t;
    f[0]=1;
    for(i=1;i<=4;i++){
        for(int j=c[i];j<N;j++){
            f[j]+=f[j-c[i]];
        }
    }
    while(t--){
        solve();
    }
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/14587797.html