首页 > 其他分享 >背包计数问题的多项式优化

背包计数问题的多项式优化

时间:2024-08-04 19:06:06浏览次数:13  
标签:背包 frac ln 多项式 01 计数问题 +...+ 式子

此优化针对以下计数问题:

n 件物品,背包容量为 m,第 i 件物品体积为 \(a_i\),求装满的方案数。(01背包)

n 种物品,背包容量为 m,第 i 件物品体积为 \(a_i\),数量无限,求装满的方案数。(完全背包)

n 种物品,背包容量为 m,第 i 件物品体积为 \(a_i\),数量为 \(b_i\),求装满的方案数。(多重背包)

\((1\le n\le1e5, 1\le m\le1e5, 1\le a_i,b_i \le 1e5)\)

不止求装满的方案数,用多项式优化后求装任意体积都是 \(O(mlogm)\)。


01背包计数

首先来看计数01背包的生成函数:

第 i 个物品:\(G_i(x) = 1+x^{a_i}\)

\(x^0\) 项表示不选,\(x^{a_i}\) 表示选,占体积为 \(a_i\)。

那么刚好装满容量为 k 的背包的方案数为:\(G(x)[x^k]=\prod\limits_{i=1}^nG_i(x)[x^k]=(1+x^{a_1})(1+x^{a_2})...(1+x^{a_n})[x^k]\)

这个式子看起来很好求,和我们之前遇到的另一个式子很像:\((x+a_1)(x+a_2)...(x+{a_n})\),这个式子就可以用分治NTT来求。

但是上面的式子次数太高了,如果用分治NTT来做,分治的最底层就已经爆炸了。

我们用一个小技巧,这种连乘的算式先取个对数 \(ln\),就可以变成相加的形式,求和之后再 \(exp\) 回去就是原式:

\(G(x)=exp(ln(1+x^{a_1})+ln(1+x^{a_2})+...+ln(1+x^{a_n}))\)

每个物品的式子都求一遍 \(ln\) 再挨个相加,这个复杂度仍然是平方的。

但是我们发现 \(G(x)\) 的每一个因式都只有两项,这个式子可以直接套用麦克劳林公式手算:\(ln(1+x)=x-\frac{x^2}{2}+\frac{x^3}{3}-\frac{x^4}{4}+...+(-1)^n\frac{x^{n+1}}{n+1}\)

把 \(x\) 换成 \(x^a\) :\(ln(1+x^a)=x^a-\frac{x^{2a}}{2}+\frac{x^{3a}}{3}-\frac{x^{4a}}{4}+...+(-1)^n\frac{x^{(n+1)a}}{n+1}\)

我们发现在总容量为 m 的限制下,一个体积为 a 的物品式子中有用的项只有 \(\frac ma\) 个,其余项为0。

我们记录每种体积的物品有几个,那么每一个不同的 a 只会算一次,\(\sum\frac m a\) 的复杂度是调和级数的 \(mlogm\)。于是我们就解决了这个问题。


完全背包计数

洛谷有个板子题:P4389 付公主的背包,想要代码的可以看这题的题解。


和01背包原理一样,将生成函数先取对数,相加后再 \(exp\) 回去。

只是现在每种物品有无限个,因此生成函数式子稍有不同:

\(G_i(x)=1+x^{a_i}+x^{2a_i}+...+x^{na_i}+...\)

\(G_i(x)=\sum\limits_{j=0}^{\infty}x^{j·a_i}\)

\(G_i(x)=\frac{1}{1-x^{a_i}}\)

至于这个式子怎么转化的,那就是生成函数的基础了。

我们将这些式子取对数再相加:

\(ln(G_i(x))=ln(\frac{1}{1-x^{a_i}})=-ln(1-x^{a_i})=x^{a_i}+\frac{x^{2{a_i}}}{2}+\frac{x^{3{a_i}}}{3}+\frac{x^{4{a_i}}}{4}+...+\frac{x^{(n+1)a}}{n+1}\)

所以几乎和01背包的式子一样。

多重背包计数

和前者一样,也是只有生成函数式子有不同。

第 i 种物品有 \(b_i\) 个,因此生成函数有 \(b_i+1\) 项:

\(G_i(x)=1+x^{a_i}+x^{2a_i}+...+x^{b_ia_i}\)

\(G_i(x)=\frac{1-x^{b_ia_i}}{1-x^{a_i}}\)

取对数后分母取负,就和完全背包的式子形式一样了,注意分子在调和级数去重时要按照 a*b 的值。

标签:背包,frac,ln,多项式,01,计数问题,+...+,式子
From: https://www.cnblogs.com/maple276/p/18342090

相关文章

  • C++动态规划(01背包)
    例题1:有 N 个物品,从 1 到 N 编号。对于每个 i(1≤i≤N),物品 i 的重量是 wi​ 价值是 vi​。太郎决定从 N 个物品里选一些放进背包带回家。太郎的背包的容量是 W,因此放进背包的物品的总重量不能超过 W。求太郎带回家的物品的总价值可能达到的最大值。1.贪......
  • 背包DP
    背包DP是线性DP中一种特殊的DP。01背包最基础的背包,有\(n\)件物品,背包容量为\(V\),每件物品只有一件。可以使用空间优化,一般是原地滚动,此时注意容量需要从后往前更新,否则会一个状态更新多次。时间复杂度为\(O(nV)\)。核心代码voidsolve(){intn,V;cin>>n>>......
  • 多项式学习笔记(一)(2024.7.6)
    声明:在本节范围内,所有同余号(多项式运算)均在\((\text{mod}x^n)\)意义下进行;所有等号(代数运算)均在模某个质数\(p\)意义下进行。暴力多项式计算加法\(H(x)=F(x)+G(x)\),求\(H(x)\)解:类比高精度加法\(h_i=f_i+g_i\),复杂度\(O(n)\)#include<bits/stdc++.h>usingnames......
  • 代码随想录训练第三十天|01背包理论基础、01背包、LeetCode416.分割等和子集
    文章目录01背包理论基础01背包二维dp数组01背包一维dp数组(滚动数组)416.分割等和子集思路01背包理论基础背包问题的理论基础重中之重是01背包,一定要理解透!leetcode上没有纯01背包的问题,都是01背包应用方面的题目,也就是需要转化为01背包问题。所以我先通过纯01背......
  • 代码随想录训练第三十二天|完全背包理论基础、LeetCode518.零钱兑换II、LeetCode377.
    文章目录完全背包理论基础完全背包总结518.零钱兑换II思路一维数组二维数组377.组合总和Ⅳ思路卡码网70.爬楼梯(进阶版)思路完全背包理论基础完全背包有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i]。每件物品都有无......
  • 代码随想录训练第三十三天|LeetCode322. 零钱兑换、LeetCode279.完全平方数、LeetCode
    文章目录322.零钱兑换思路279.完全平方数思路139.单词拆分思路多重背包背包总结遍历顺序01背包完全背包总结322.零钱兑换给你一个整数数组coins,表示不同面额的硬币;以及一个整数amount,表示总金额。计算并返回可以凑成总金额所需的最少的硬币个数。如果......
  • 一种优化 01 可行背包的方法
    source:abc221g有\(n\)个物品,体积分别为\(a_{1,2,\dots,n}\),要求从中选出若干个物品使得体积和为\(V\)。令\(A=\maxa_i\),\(V\lenA\)。一般的01背包做法是\(O(n^2A)\)的,但存在一种相对简单的做法可以做到复杂度\(O(nA)\)。下面描述这个做法。首先任意排列这个物......
  • 多项式基础内容小记
    0.基础知识:关于多项式的定义:多项式:一个形如\(f(x)=\sum_{i=0}^na_ix^i\)的有限和式被称为多项式。系数:多项式第\(i\)项的系数在上面就表示为\(a_i\)。度(次数):多项式中最高次数的项的次数就被称为该多项式的度,也称次数。多项式表示法:多项式有两种表示法:......
  • 二维费用背包问题
    宠物小精灵之收服题解:设状态\(dp[i][j][k]\)表示从前\(i\)个物品中选择,物品的费用\(1\)为\(j\),费用\(2\)为\(k\)的最大选择数量。则状态转移方程为:\[dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-v_1[i]][k-v_2[i]]+1)\]跟普通01背包一样,第一维可以直接......
  • IPA多项式承诺方案--(2)预备知识
    基于内积定理(InnerProductArgument)实现的多项式承诺方案,为了方便,简称为IPA多项式承诺方案。在阅读承诺方案前,需要掌握Pedersen承诺、内积和Σ\SigmaΣ协议相关知识,Peder......