zoukankan      html  css  js  c++  java
  • [HAOI2008]硬币购物

    题目描述

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

    输入输出格式

    输入格式:

    第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s

    输出格式: 

    每次的方法数

    输入输出样例

    输入样例#1:
    1 2 5 10 2
    3 2 3 1 10
    1000 2 2 2 900
    
    输出样例#1:
    4
    27
    

    说明

    di,s<=100000

    tot<=1000

    题解:

    一开始认为要求出一个4元方程的解的个数,用容斥求出所有GCD(a,b,c,d)|si的解

    但时间复杂度太高,且条件限制不好做。

    后面看到一种解法:

    用dp求f[i]为钱数为i时的方案总数

    显然f[i]=signma(f[i-c[j]])

    复杂度为O(4*s)

    再用容斥原理求出所有方案,减去1超出限制,再减去2超限,还有3和4。再加上1,2超限.....

    i超出限制的方案为f[si-(d[j]+1)*c[j]]

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 long long c[5],d[5],tot;
     7 long long f[1000005],ans;
     8 int main()
     9 {long long i,j,s;
    10     cin>>c[1]>>c[2]>>c[3]>>c[4]>>tot;
    11     f[0]=1;
    12     for (i=1;i<=4;i++)
    13     for (j=c[i];j<=100000;j++)
    14     {
    15         f[j]+=f[j-c[i]];
    16     }
    17     for (i=1;i<=tot;i++)
    18     {
    19         for (j=1;j<=4;j++)
    20         scanf("%I64d",&d[j]);
    21         scanf("%I64d",&s);
    22         ans=f[s];
    23         if ((d[1]+1)*c[1]<=s)
    24         ans-=f[s-(d[1]+1)*c[1]];
    25         if ((d[2]+1)*c[2]<=s)
    26         ans-=f[s-(d[2]+1)*c[2]];
    27         if ((d[3]+1)*c[3]<=s)
    28         ans-=f[s-(d[3]+1)*c[3]];
    29         if ((d[4]+1)*c[4]<=s)
    30         ans-=f[s-(d[4]+1)*c[4]];
    31         
    32         if ((d[1]+1)*c[1]+(d[2]+1)*c[2]<=s)
    33         ans+=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]];
    34         if ((d[1]+1)*c[1]+(d[3]+1)*c[3]<=s)
    35         ans+=f[s-(d[1]+1)*c[1]-(d[3]+1)*c[3]];
    36         if ((d[1]+1)*c[1]+(d[4]+1)*c[4]<=s)
    37         ans+=f[s-(d[1]+1)*c[1]-(d[4]+1)*c[4]];
    38         if ((d[3]+1)*c[3]+(d[2]+1)*c[2]<=s)
    39         ans+=f[s-(d[3]+1)*c[3]-(d[2]+1)*c[2]];
    40         if ((d[4]+1)*c[4]+(d[2]+1)*c[2]<=s)
    41         ans+=f[s-(d[4]+1)*c[4]-(d[2]+1)*c[2]];
    42         if ((d[3]+1)*c[3]+(d[4]+1)*c[4]<=s)
    43         ans+=f[s-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
    44         
    45         if ((d[1]+1)*c[1]+(d[2]+1)*c[2]+(d[3]+1)*c[3]<=s)
    46         ans-=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]];
    47         if ((d[4]+1)*c[4]+(d[2]+1)*c[2]+(d[3]+1)*c[3]<=s)
    48         ans-=f[s-(d[4]+1)*c[4]-(d[2]+1)*c[2]-(d[3]+1)*c[3]];
    49         if ((d[1]+1)*c[1]+(d[4]+1)*c[4]+(d[3]+1)*c[3]<=s)
    50         ans-=f[s-(d[1]+1)*c[1]-(d[4]+1)*c[4]-(d[3]+1)*c[3]];
    51         if ((d[1]+1)*c[1]+(d[4]+1)*c[4]+(d[2]+1)*c[2]<=s)
    52         ans-=f[s-(d[1]+1)*c[1]-(d[4]+1)*c[4]-(d[2]+1)*c[2]];
    53         
    54         if ((d[1]+1)*c[1]+(d[2]+1)*c[2]+(d[3]+1)*c[3]+(d[4]+1)*d[4]<=s)
    55         ans+=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*d[4]];
    56         cout<<ans<<endl;
    57     }
    58 }
  • 相关阅读:
    shiro标签
    ssm项目整合shiro
    关于POI读取模板的单元格位为null,或者无法正确获取样式的简单处理方案
    为什么wait的条件放在while里面,用if就不行
    Dto中有List<DTO> children,那么如何把List<Dto>转为List<VO>
    开发踩过的坑
    POI一直不能给sheet赋值
    写给研发的需求能不能不要废话
    写着写着就不知道自己定义的方法是干嘛的了
    一个if else的问题,卡了一个小时,我也是……
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7246935.html
Copyright © 2011-2022 走看看