解題報告:HDU_6042 Journey with Knapsack 生成函數

題目鏈接


題意:

你有一個容量爲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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章