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

来源:互联网 发布:管家婆数据导入 编辑:程序博客网 时间:2024/06/13 13:02

题目链接


题意:

你有一个容量为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;}



原创粉丝点击