首页 > 其他分享 >洛谷-P1450 硬币购物

洛谷-P1450 硬币购物

时间:2022-12-16 17:34:07浏览次数:79  
标签:cnt 洛谷 P1450 硬币 int sum 容斥 ll dp

P1450 硬币购物

容斥 || \(dp\) + 单调队列优化

容易看出是个多重背包,然后拿单调队列优化一下后,计算量为 \(O(4ns)\)

这种做法的话就是单调队列优化板子题

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll dp[5][maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int c[5], d[5];
    for(int i=1; i<=4; i++) cin >> c[i];
    int t;
    cin >> t;
    dp[0][0] = 1;
    while(t--)
    {
        for(int i=1; i<=4; i++) cin >> d[i];
        int s;
        cin >> s;
        for(int i=1; i<=4; i++)
        {
            for(int j=0; j<c[i]; j++) dp[i][j] = dp[i - 1][j];
            for(int j=c[i]; j<c[i]+c[i]; j++)
            {
                int l = j - c[i], r = j - c[i];
                ll sum = dp[i - 1][j - c[i]];
                for(int k=j; k<=s; k+=c[i])
                {
                    r = k;
                    if((r - l) / c[i] > d[i])
                    {
                        sum -= dp[i - 1][l];
                        l += c[i];
                    }
                    sum += dp[i - 1][k];
                    dp[i][k] = sum;
                }
            }
        }
        cout << dp[4][s] << "\n";
    }
    return 0;
}

容斥的做法:

这个问题可以抽象成为一个带有限制的方程求方案数

\[\sum_{i=1}^{4} (c_i \times cnt_i) = s, cnt_i \le d_i \]

考虑容斥的话,方案数为:所有方案数 - 所有非法方案数

所有非法方案数可以通过枚举 \(cnt_i > d_i\) 的情况容斥求出

根据容斥定理,非法的方案数应该是 奇数个 \(cnt_i\) 非法的情况 - 偶数个 \(cnt_i\) 非法的情况

可以先做一个完全背包 \(dp[j] = dp[j] + dp[j - c_i]\)

那么 \(dp[x]\) 的意义就为,用 \(4\) 种硬币在无限制的条件下凑齐 \(x\) 块钱所有的方案数

因此在某个非法限制下的方案数就可以直接得到,例如在第 \(1\) 种硬币中,\(cnt_1 > d_1\),其他硬币数量不做约束的情况下,方案数为 \(dp[s - (d_1 + 1) \times c_1]\)

二进制枚举,然后容斥即可

计算量为:\(O(4s_{max} + n * (4 * 2^4))\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll dp[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int c[4], d[4];
    dp[0] = 1;
    for(int i=0; i<4; i++)
    {
        cin >> c[i];
        for(int j=c[i]; j<maxn; j++)
            dp[j] += dp[j - c[i]];
    }
    int t;
    cin >> t;
    while(t--)
    {
        for(int i=0; i<4; i++) cin >> d[i];
        int s;
        cin >> s;
        ll ans = 0;
        for(int i=0; i<=15; i++)
        {
            int cnt = 0;
            ll sum = 0;
            for(int j=0; j<4; j++)
            {
                if(i >> j & 1)
                {
                    cnt++;
                    sum += (d[j] + 1) * c[j];
                }
            }
            if(sum > s) sum = 0;
            else sum = dp[s - sum];
            if(cnt & 1) sum = -sum;
            ans += sum;
        }
        cout << ans << "\n";
    }
    // cout << endl;
    return 0;
}

标签:cnt,洛谷,P1450,硬币,int,sum,容斥,ll,dp
From: https://www.cnblogs.com/dgsvygd/p/16987915.html

相关文章

  • 剑指offer103:最少的硬币数目
    题目:给定不同面额的硬币coins和一个总金额amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回-1。你可以认......
  • 洛谷 P1020 导弹拦截(递增子串 DP )
    题目大意:有一个数列,我们要获取一组子串,这个子串必须单调不增。问:(1)最长我们可以获取多长的这种子串(2)这个数列中最多有多少种这种子串解题思路:其中问题一是很典型的DP问题,最......
  • 洛谷 P1087 FBI树
    题目大意:已知一棵树由字符串组成,规定:若节点全1把这节点称为I节点。若节点全0把节点称为B节点。若节点含0同时含1把节点称为F节点。现在有一个字符串N长,左子树是前一半字......
  • 洛谷 P1088 火星人(乱搞)
    题目大意:已知有一串数字,问在原来的数字串的字典序加m后,应该输出多少解题思路:最简便的做法是用next_permutation,这个生成的全排列可以按照字典序递增,这里我用的是搜索的方法......
  • 洛谷 P1113 杂务(拓扑排序,递归)
    题目大意:有一个有向无圈图,每个节点看作一个任务,一个任务需要完成必须先完成父亲节点的任务,每个任务都有耗时。假设现在所有不相关任务都可以并行执行,问最短多少时间可以把所......
  • 洛谷 P1996 约瑟夫问题
    问题简介:小朋友围城一圈,从1号开始报数,报到M的那位同学出局,然后下一位同学报1,循环上述过程直到所有同学出局。输出依次出局的小朋友的号码解题思路:没什么好说的,就是模拟,出局......
  • 洛谷 P1233 木棍加工(贪心,递增子串DP)
    题目大意:有矩形A1,A2......An.每个矩形有长宽w,h。现在已知cost:(1)若矩形a的w,h小于矩形b的w,h,那么没有cost(2)其它情况cost+1.现在已知矩形A1,A2...,问怎么得到最少cost.解题思......
  • 洛谷 P1057 传球游戏(背包DP)
    题目大意:有n个人围成一圈,每个人可以把手上的球传给左边或者右边,现在小明开始传球,问m次后,把球传回给自己的次数。解题思路:考虑DP,使用带记忆的DP, 首先我们的状态可以设为[还......
  • 洛谷 P5143 攀爬者 题解
    原题链接P5143攀爬者解析内心OS第一眼看上去:他**滴,这么离谱的公式,这还是正常的橙题吗?1分钟后······这么简单的题,还好意思当橙题?(请忽略上方内容)......
  • 「题解」洛谷 P8850 [JRKSJ R5] Jalapeno and Garlic
    2022.12upd:原先代码锅了,重写了一份。看上去是比较常规的题,应当需要更灵敏的直觉和更快的速度解决这道题。首先考虑若已经确定一个\(x\),那么贪心修改策略就是随便找一个......