有限背包计数问题
https://class.51nod.com/Html/Textbook/ChapterIndex.html#chapterId=335&textbookId=126
https://class.51nod.com/Html/Challenge/Problem.Html#problemId=1597
如有限背包计数问题
发现对于物品
对于小的那一类,可以用临时数组维护对应余数的和(像多重背包一样),然后超出范围的再减去。
大的那一类,考虑每次添加一个新的数或者让所有数+1(这样就能涵盖所有的情况,所有数+1相当于偏移,你想让它等于多少,就在最后一个数加入前特定时间加入即可)。
复杂度
#include<iostream>
#include<cmath>
#include<cstring>
#define add(a,b) (a+=b)>=mod&&(a-=mod)
#define sub(a,b) (a-=b)<0&&(a+=mod)
using namespace std;
const int N=100010,mod=23333333,Q=320;
int n,q,tmp[Q],f[2][N],g[2][N];
int main(){
#ifdef LOCAL
freopen("1.txt","r",stdin);
#endif
#ifndef LOCAL
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
#endif
cin>>n;
q=sqrt(n)+1;
f[0][0]=1;
for(int i=1;i<q;++i){
int I=i&1,L=!I;
memset(tmp,0,i*4);
int mo=-1;
for(int j=0;j<=n;++j){
++mo;
if(mo==i)mo=0;
add(tmp[mo],f[L][j]);
f[I][j]=tmp[mo];
if(j>=i*i)sub(tmp[mo],f[L][j-i*i]);//can't reach
}
}
int qq=(q-1)&1;
// for(int i=1;i<q;++i,puts(""))
// for(int j=0;j<=n;++j)
// cout<<f[i][j]<<' ';
g[0][0]=1;
int ans=f[qq][n],nq=n/q;
for(int i=1;i<=nq;++i){int I=i&1,L=!I;
g[I][0]=0;
for(int j=q;j<=n;++j){
g[I][j]=g[L][j-q];
add(g[I][j],g[I][j-i]);
add(ans,1ll*g[I][j]*f[qq][n-j]%mod);
}}
cout<<ans;
return 0;
}
本文作者:wscqwq
本文链接:https://www.cnblogs.com/wscqwq/p/18315036
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2023-07-21 BoxInBox
2023-07-21 Make10Again
2023-07-21 Vouchers