[hdu6042]Journey with Knapsack

題目大意

Rosemary有一個容積爲2n的揹包,還有n種物品,第i種物品的容積爲i,有ai個,保證a是非負整數且遞增(即ai>=0ai<ai+1 )。
現在lihua擺出了m個裝備幫助Rosemary完成他的旅行,第i個裝備的容積爲bi,Rosemary必須選擇恰好一個裝備以及若干個物品裝進揹包去旅行,要求揹包裝滿,問有多少種方案。
兩種方案不同,當且僅當選擇的裝備不同,或者某種物品的選擇數量不同。
n<=5*10^4。對10^9+7取模。

生成函數

不妨設選擇物品的生成函數爲F(x)
那麼ans=mi=1[x2nbi]F(x)
對於第i 種物品,其生成函數爲1+xi+x2i++xaii
1x(ai+1)i1xi
F(x)=ni=1(1x(ai+1)i)ni=111xi
我們分開兩部分考慮。

第一部分

注意到ai>=0ai<ai+1 ,這意味着ai>=i1
那麼(ai+1)i>=i2
因爲我們的多項式要在模x2n+1 意義下計算,因此可以發現只有前根號個有用。
不妨先算出其餘部分,最後把這根號個單項乘上去,那麼複雜度爲O(nn)

第二部分

我們希望計算ni=111xix2n+1
我們探討發現這個式子的意義其實是把一個數拆分成一些<=n的正整數之和的本質不同方案數。
這樣不好做,我們進行一些轉化。以下均默認在模x2n+1 意義下進行。
ni=111xi
=2ni=111xi2ni=n+1(1xi)
=2ni=111xi(12ni=n+1xi)
P(x)=ni=111xixn
則前面部分就是P(x) 。後面部分很容易處理。
現在的意義是把一個數拆分成任意一些正整數之和的本質不同方案數,即拆分數的計算。

拆分數

計算拆分數有一個經典做法。
即五邊形數定理。
p(n)=k>=1(1)k+1[p(nk(3k+1)2)+p(nk(3k1)2)]
證明請研究http://blog.csdn.net/visit_world/article/details/52734860
根據該式子可以在O(nn) 的時間內預處理拆分數。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=50000+10,mo=1000000007;
int f[maxn*2],g[maxn*2],h[maxn*2],a[maxn];
int i,j,k,l,r,t,n,m,ans,ca;
int main(){
    while (scanf("%d%d",&n,&m)!=EOF){
        ca++;
        fo(i,1,n) scanf("%d",&a[i]);
        g[0]=1;
        fo(i,1,2*n){
            g[i]=0;
            fo(k,1,n){
                if (k%2) r=1;else r=-1;
                t=k*(3*k-1)/2;
                if (t>i) break;
                (g[i]+=g[i-t]*r)%=mo;
                t=k*(3*k+1)/2;
                if (t>i) continue;
                (g[i]+=g[i-t]*r)%=mo;
            }
        }
        fo(k,1,n){
            t=(a[k]+1)*k;
            if (t>2*n) break;
            fd(i,2*n,t) (g[i]-=g[i-t])%=mo;
        }
        fo(i,0,2*n) h[i]=0;
        fo(i,0,n-1) (h[i+n+1]-=g[i])%=mo;
        fo(i,1,2*n) (h[i]+=h[i-1])%=mo;
        fo(i,0,2*n) f[i]=(g[i]+h[i])%mo;
        ans=0;
        fo(i,1,m){
            scanf("%d",&t);
            (ans+=f[2*n-t])%=mo;
        }
        (ans+=mo)%=mo;
        printf("Case #%d: %d\n",ca,ans);
    }
}
發佈了836 篇原創文章 · 獲贊 317 · 訪問量 59萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章