• [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 }
  • 相关阅读:
    Google搜索引擎如何运作:不会手动调整结果
    一个Ruby脚本
    IE灭绝!?
    除Windows之外的其他操作系统
    刚收到的新书
    奇怪的计算机语言
    小巧的menuetOS
    Ruby学习笔记(1)
    一个通知
    总结 asp.net 和 javascript获取本地IP(MAC)和服务器IP(MAC)的方法
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7246935.html
Copyright © 2020-2023  润新知