[背包DP || 多项式] 51Nod 1597 有限背包计数问题

来源:互联网 发布:淘宝商品管理 编辑:程序博客网 时间:2024/06/02 07:39

这是个多重背包 直接做肯定接受不了时间复杂度
我们看当体积大于 n 时 是用不完的 是个完全背包
但还是接受不了复杂度 再观察 体积大的总共只可能取n
fi,j表示拿了 i 个 总体积为 j 的方案数
这样转移 每次全部加1 或者新加入一个n+1

体积小的嘛 总共根号种 前缀和转一下 是可以做到O(nn)
总复杂度 O(nn)

#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>using namespace std;typedef long long ll;const int P=23333333;const int N=100005;int n,m;int f[2][N];int F1[N],F2[N];#define F(x) (x<0?0:f[t][x])int main(){  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  scanf("%d",&n); m=sqrt(n);  int t; f[t=0][0]=1;  for (int i=1;i<=m;i++,t^=1){    for (int j=0;j<=n;j++)      (f[t][j]+=F(j-i))%=P;    for (int j=0;j<=n;j++)      f[t^1][j]=(F(j)+P-F(j-(i+1)*i))%P;  }  for (int i=0;i<=n;i++) F1[i]=f[t][i];  f[t=0][0]=1; for (int i=1;i<=n;i++) f[t][i]=0;  F2[0]=1;  for (int i=1;i<=m;i++,t^=1)    for (int j=0;j<=n;j++){      f[t^1][j]=((j>=i?f[t^1][j-i]:0)+F(j-m-1))%P;      (F2[j]+=f[t^1][j])%=P;    }  ll ans=0;  for (int i=0;i<=n;i++)    ans+=(ll)F1[i]*F2[n-i]%P;  printf("%lld\n",ans%P);  return 0;}

这个我们再喂给OEIS 又找到辣
然后知道了生成函数就可以大力一发科技
大佬的题解 orzz

0 0
原创粉丝点击