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

2017 Multi-University Training Contest - Team 1



        人生第一道母函数的题目,纪念一下……

        我就稍微说说母函数吧。母函数分为普通型母函数和指数型母函数,两个分别对应解决组合问题和排列问题。关于它的用法表示,这个自己看看百度百科吧,个人感觉百科已经说得很清楚了。大致意思就是可以通过母函数某一次项的系数来确定结果。

        然后这题的话,总共有n个物品,第i个物品的体积为i,数量为ai。那么物品i对应的母函数就是1+x^i+x^2i+x^3i+……+x^ai。剩下的直接就看官方题解吧,够清楚了……

                               2017多校训练赛第一场 HDU 6042 (母函数)_第1张图片

                               2017多校训练赛第一场 HDU 6042 (母函数)_第2张图片

        如果你觉得乱,我也没办法,感觉这题真的得靠自己理解……具体见代码:

#include
#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;
} 


你可能感兴趣的:(---------Online,Judge--------,HDU,2017HDU多校赛,组合计数,母函数)