1. 程式人生 > >2017多校訓練賽第一場 HDU 6042 (母函式)

2017多校訓練賽第一場 HDU 6042 (母函式)

Journey with Knapsack

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 164    Accepted Submission(s): 61

Problem Description

KazaQ has a knapsack with volume 2n and n kinds of food, where the i-th food's volume is i and the number of it is ai (1in

) meaning that the number of the i-th food that KazaQ would like to store into the knapsack is no more than ai, otherwise he would feel sick. KazaQ has a unique taste, therefore all the ai are distinct.
KazaQ plans to make a journey but after that he needs to store some food and one piece of equipment into the knapsack. He has m
pieces of equipment, of which the i-th piece's volume is bi (1in). Notice that volumes of different pieces may be the same.
Assuming that two plans are distinct if and only if they contain different pieces of equipment or there exists at least one integer k (1kn) satisfying the number of the k
-th food to store into the knapsack in this two plans are different, KazaQ is intend to know what is the total number of distinct plans for storing one piece of equipment and some food into the knapsack fully. Can you help him?
The answer may be very large, so you only need to give the value of the answer modulo 109+7.

Input

The input contains multiple test cases.
For each test case:
The first line contains two positive integers n and m, satisfying 1n5104,1m2n.
The second line contains n distinct non-negative integers a1,a2,,an, satisfying 0a1<a2<<an2n.
The third line contains m positive integers b1,b2,,bm, satisfying 1b1,b2,,bm2n.
About 100 test cases in total, where no more than 5 cases satisfy n103.

Output

For each test case, output "Case #x: y" in one line (without quotes), where x indicates the case number starting from 1 and y denotes the answer of corresponding case.

Sample Input

1 1 1 1 2 2 1 2 3 4 3 3 1 2 3 2 3 3

Sample Output

Case #1: 1 Case #2: 2 Case #3: 6

Source

        人生第一道母函式的題目,紀念一下……

        我就稍微說說母函式吧。母函式分為普通型母函式和指數型母函式,兩個分別對應解決組合問題和排列問題。關於它的用法表示,這個自己看看百度百科吧,個人感覺百科已經說得很清楚了。大致意思就是可以通過母函式某一次項的係數來確定結果。

        然後這題的話,總共有n個物品,第i個物品的體積為i,數量為ai。那麼物品i對應的母函式就是1+x^i+x^2i+x^3i+……+x^ai。剩下的直接就看官方題解吧,夠清楚了……

                              

                              

        如果你覺得亂,我也沒辦法,感覺這題真的得靠自己理解……具體見程式碼:

#include<bits/stdc++.h>
#define mod 1000000007
#define LL long long
#define N 200010
using namespace std;

LL dp[N],f[N];
int n,m;

int main()
{
    int T_T=0; dp[0]=1;
    for(int i=1;i<=100000;i++)					//預處理五邊形數
    {
        for(int j=1,k=1;k<=i;k+=3*j+1,j++)
        {
            if (j&1) dp[i]+=dp[i-k]; else dp[i]-=dp[i-k];
            dp[i]=(dp[i]%mod+mod)%mod;
        }
        for(int j=1,k=2;k<=i;k+=3*j+2,j++)
        {
            if (j&1) dp[i]+=dp[i-k]; else dp[i]-=dp[i-k];
            dp[i]=(dp[i]%mod+mod)%mod;
        }
    }
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0;i<=2*n;i++)
            f[i]=dp[i];
        for(int i=1;i<=n;i++)
        {
            int x; scanf("%d",&x);
            if ((LL)(x+1)*i<=2*n)
                for(int j=2*n;j>=(x+1)*i;j--)			//類似揹包dp的方法減去第一部分
                {
                    f[j]-=f[j-(x+1)*i];
                    f[j]=(f[j]%mod+mod)%mod;
                }
        }
        for(int i=1,s=1;i<=2*n;i++)				//字首和的方式減去這一部分
        {
            f[i+n]-=s; s+=f[i];
            f[i+n]=(f[i+n]%mod+mod)%mod;
            if (s>=mod) s%=mod;
        }
        LL ans=0;
        for(int i=1;i<=m;i++)					//再嘗試放不同的equipment來統計結果
        {
            int x; scanf("%d",&x);
            ans+=f[2*n-x];
            if (ans>=mod) ans%=mod;
        }
        printf("Case #%d: %I64d\n",++T_T,ans);
    }
    return 0;
}