bzoj 1042

完全背包预处理再容斥。

符合条件的付款方法数=所有付款方法数-不符合的方法数。

所有付款方法数可以用完全背包求出。

根据容斥原理,不符合的方法数等于第一种硬币不符合的方案数+第二种硬币不符合的方案数+……-第一种和第二种硬币都不符合的方案数-第一种和第三种硬币都不符合的方案数-……+第一种和第二种和第三种硬币都不符合的方案数+第一种和第二种和第四种硬币都不符合的方案数+……-四种硬币都不符合的方案数。

推荐用DFS来实现,比较好写。时间复杂度大概是O(S+T)。

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxs=100001;
long long read(){
    char c; while(!isdigit(c=getchar())); long long x=c-'0';
    while(isdigit(c=getchar())) x=x*10+c-'0'; return x;
}
long long ans,c[4],d[4],s,f[maxs];
void dfs(int o,int s,int num){
    if(s<0) return;
    if(o==4){
        if(num&1) ans-=f[s];
        else ans+=f[s];
        return;
    }
    dfs(o+1,s,num);
    dfs(o+1,s-(d[o]+1)*c[o],num+1);
}
int main(){
    f[0]=1;
    for(int i=0;i<4;i+=1) c[i]=read();
    for(int i=0;i<4;i+=1)
        for(int j=c[i];j<maxs;j+=1)
            f[j]+=f[j-c[i]];
    int t=read();
    while(t--){
        ans=0;
        for(int i=0;i<4;i+=1) d[i]=read();
        dfs(0,s=read(),0);
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2017-10-23 13:18  或是七一  阅读(...)  评论(... 编辑 收藏