• bzoj 1042: [HAOI2008]硬币购物


    1042: [HAOI2008]硬币购物

    Time Limit: 10 Sec  Memory Limit: 162 MB

    Description

      硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买s
    i的价值的东西。请问每次有多少种付款方法。

    Input

      第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000

    Output

      每次的方法数

    Sample Input

    1 2 5 10 2
    3 2 3 1 10
    1000 2 2 2 900

    Sample Output

    4
    27

    HINT

     

    Source

    如果用裸的有限背包做,那么时间复杂度就上天了;

    我们可以把它先当做无限背包预处理出来;

    那么di个硬币的方案数就是 dp[s]-dp[s-(di+1)*ci];

    如果有多个限制的硬币,那么会有重复;

    运用容斥原理,只有4个数,暴力求解即可;

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #define N 100000
    using namespace std;
    
    int c[5],tot,s,d[5];
    long long dp[N+8],num,res;
    
    void dfs(int u,int flag,int sum){
        if(sum<0) return;
        if(u==5){
            if(flag&1){
                res-=dp[sum];
            }else{
                res+=dp[sum];
            }
            return;
        }
        dfs(u+1,flag+1,sum-(d[u]+1)*c[u]);
        dfs(u+1,flag,sum);
    }
    
    int main(){
        memset(dp,0,sizeof(dp));
        scanf("%d%d%d%d%d",&c[1],&c[2],&c[3],&c[4],&tot);
        dp[0]=1;
        for(int i=1;i<=4;i++)
            for(int j=c[i];j<=N;j++)
                dp[j]+=dp[j-c[i]];
        for(int i=1;i<=tot;i++){
            scanf("%d%d%d%d%d",&d[1],&d[2],&d[3],&d[4],&s);
            res=0;
            num=s;
            dfs(1,0,num);
            printf("%lld
    ",res);
        }
    }
  • 相关阅读:
    白书上的BellmanFord模板
    c#中的分部类和分部方法
    c#类
    浪潮gs开发平台学习平台快速开发入门
    c#学习积累
    自定义属性编辑器
    hibernate 中的hql,nativesql ,list(),iterate() 的使用规则
    c#继承
    浪潮gs中间件服务器,客户端,数据库sqlserver安装注意事项
    c#接口
  • 原文地址:https://www.cnblogs.com/WQHui/p/7602569.html
Copyright © 2020-2023  润新知