标签:背包 LOJ sqrt int 体积 6089 物品 计数问题 mod
题意
有一个容量为 \(n\) 的背包 \(( n \le 10^5)\).
有 \(n\) 种物品, 第 \(i\) 种物品有 \(i\) 个, 体积为 \(i\).
求将背包装满的方案数.
思路
直接多重背包肯定不行, 加前缀和优化也有 \(n^2\).
考虑到, 体积大于 \(\sqrt{n}\) 的物品一定不会用完, 所以相当于一个无限背包,
对体积小于 \(\sqrt{n}\) 的物品, 做一个前缀和优化的多重背包就行了, 复杂度为 \(O(n\sqrt{n})\).
对于体积大于等于 \(\sqrt{n}\) 的物品, 直接做无限背包肯定也不行,
考虑到这些物品有一个性质 : 它们的体积是递增的, 那我们可以把无限背包的过程转化为以下两个操作,
- 往背包里加入一个体积为 \(\sqrt{n}\) 的物品.
- 把背包里所有物品的体积都 +1.
无限背包的过程其实就相当于维护了一个递增序列, 而上述的两个操作也可以构造出所有递增序列, 所以它们是等价的.
所以, 我们设 \(f[i][j]\) 为往背包中放了 \(i\) 个物品, 总体积为 \(j\) 的方案数,
- \(f[i][j]+=f[i-1][j-\sqrt{n}]\)
- \(f[i][j]+=f[i][j-1]\)
分别代表 往背包内加一个体积为 \(\sqrt{n}\) 的物品 和 把背包内所有物品体积 +1.
由于这些物品的体积都大于 \(\sqrt{n}\), 所以最多只能放 \(\sqrt{n}\) 个物品, 因此复杂度为 \(O(n\sqrt{n})\).
代码
#include<bits/stdc++.h>
using namespace std;
const int _=320+7;
const int __=1e5+7;
const int mod=23333333;
int n,t,f[__],sum[__],g[_][__],ans;
int main(){
//freopen("x.in","r",stdin);
cin>>n; t=ceil(sqrt(n));
f[0]=1; sum[0]=1;
for(int i=1;i<t;i++){
for(int j=i;j<=n;j++) f[j]=(f[j]+f[j-i])%mod;
for(int j=n;j>=(i+1)*i;j--) f[j]=((f[j]-f[j-(i+1)*i])%mod+mod)%mod;
}
g[0][0]=1;
for(int i=1;i<=t;i++)
for(int j=0;j<=n;j++){
if(j>=i) g[i][j]=(g[i][j]+g[i][j-i])%mod;
if(j>=t) g[i][j]=(g[i][j]+g[i-1][j-t])%mod;
}
for(int i=1;i<=t;i++)
for(int j=0;j<=n;j++)
g[0][j]=(g[0][j]+g[i][j])%mod;
for(int j=0;j<=n;j++)
ans=(ans+(long long)f[j]*g[0][n-j]%mod)%mod;
printf("%d\n",ans);
return 0;
}
标签:背包,LOJ,sqrt,int,体积,6089,物品,计数问题,mod 来源: https://www.cnblogs.com/brucew-07/p/12181249.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。