解题报告:HDU_6042 Journey with Knapsack 生成函数

本文探讨了一个特定的背包问题,该问题涉及在有限容量下选择武器和食物的组合方式。通过使用五边形数定理,文章提供了一种有效的解决方案,并附带详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接


题意:

你有一个容量为2*n的背包,现在有n种食物,第i种事物的体积为i,数目为ai个。还有m种武器,每种武器体积为bi。

现在要求背包里装一个武器,任意食物的方案数。


思路:

官方给的就很详细了Orz......




不懂五边形数定理的同学可以看维基的介绍:五边形数定理 分割数


代码:

#include<bits/stdc++.h>


const int N = 1e5+10;
const int mod = 1e9+7;
using namespace std;


int n=1e5,m,l;
int arr[N],dp[N],tmp[N];

void init(){
   arr[0] = 1;
   for(int i=1,j=1;i<=1000;i++){
      tmp[i] = j * ( 3 * j - 1 ) / 2;
      if(j>0)j=-j;
      else j=-j+1;
   }
   for(int i=1;i<=n;i++){
      for(int j=1,k=1;i>=tmp[j];j++,k++){
         if(k==5)k-=4;
         arr[i] += (k<=2?1:-1) * arr[i-tmp[j]];
         if(arr[i]>=mod)arr[i]-=mod;
         else if(arr[i]<0)arr[i]+=mod;
      }
   }
}


int main()
{
   init();
   int cas = 0 , x ;
   while(scanf("%d%d",&n,&m)==2){ l = n<<1;
      for(int i=0;i<=l;i++)dp[i] = arr[i];
      for(int i=1;i<=n;i++){
         scanf("%d",&x);
         long long t = 1LL * (x+1) * i;
         if(t<=l){
            for(int j=l;j>=t;j--){
               dp[j] -= dp[j-t];
               if(dp[j]<0)dp[j]+=mod;
            }
         }
      }
      for(int i=1,j=n+1,sum=dp[0];i<=n;sum+=dp[i++],j++){
         if(sum>=mod)sum-=mod;
         dp[j] -= sum;
         if(dp[j]<0)dp[j]+=mod;
      }int ans = 0;
      while(m--){
         scanf("%d",&x);
         ans += dp[l-x];
         if(ans>=mod)ans-=mod;
      }printf("Case #%d: %d\n",++cas,ans);
   }return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值