51nod 1269 Devu and Flowers

题目来源:  CodeForces
基准时间限制:2 秒 空间限制:131072 KB 分值: 160  难度:6级算法题
 收藏
 关注
N个盒子,每个盒子里面有一种颜色的花,数量为si,N个盒子里花的颜色各不相同,但同一个盒子里面的花认为是相同的,现在需要选出K朵花,有多少种不同的方案?由于结果很大,输出Mod 1000000007的结果即可。
例如:3个盒子,花的数量分别为1 3 2,需要选出5朵花,那么可以有如下3种方案:{1, 2, 2}, {0, 3, 2}, {1, 3, 1}。
Input
第1行:两个数N, K。N为盒子的数量,K为需要的花朵的数量(1 <= N <= 20, 1 <= K <= 10^18)
第2 - N + 1行:每行1个数,对应盒子中花朵的数量Si(1 <= Si <= 10^16)
Output
输出方案的数量Mod 1000000007。
Input示例
3 5
1
3
2
Output示例
3

思路:
1.转换为求G(x)=(1+x+x^2+...+x^s1)*(1+x+x^2+...+x^s2)*...*(1+x+x^2+...+x^sn)
   中x^k的系数
2.在每个盒子花无限的情况下ans=C(k+n-1,n-1)
   ans等于a1+a2+...+an=k这个n元一次方程的解的个数,ai指x的贡献值
   不理解可以看下下面这篇文章
   https://wenku.baidu.com/view/843aff00bed5b9f3f90f1c25.html
3.因为有s作为限制,所以我们可以枚举对于第i个盒子来说,选择花的个数超出si的方案数,          (pass:包括其他盒子超出个数的情况,所以得用容斥)方法数即为C(k+n-1-s1-1,n-1),
   用插板,si+1是因为考虑可以取0个的情况
代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
typedef long long LL;
const LL MOD=1000000007;
using namespace std;
LL s[30];
LL quick_pow(LL a,LL b)
{
    LL c=1;
    while(b)
    {
        if(b&1)
            c=(a*c)%MOD;
        a=(a*a)%MOD;
        b>>=1;
    }
    return c;
}
LL inv(LL n)
{
    return quick_pow(n,MOD-2);
}
LL C(LL n,LL m)
{
    if(n<m)
        return 0;
    LL a=1,b=1;
    for(LL i=0;i<m;i++)
    {
        a=a*(n-i)%MOD;
        b=b*(m-i)%MOD;
    }
    return (a*inv(b))%MOD;
}
LL Lucas(LL n, LL m)
{
    return m?Lucas(n/MOD,m/MOD)*C(n%MOD,m%MOD)%MOD:1;
}
int main()
{
    LL n,k,ans;
    while(scanf("%lld%lld",&n,&k)!=-1)
    {
        for(int i=0;i<n;i++)
            scanf("%lld",&s[i]);
        ans=0;
        for(int i=0;i<(1<<n);i++)
        {
            LL cnt=0,sum=k;
            for(int j=0;j<n;j++)
            {
                if(i&(1<<j))
                {
                    cnt++;
                    sum-=s[j]+1;
                }
            }
            if(sum<0)
                continue;
            if(cnt&1)
                ans=(ans-Lucas(sum+n-1,n-1)+MOD)%MOD;
            else
                ans=(ans+Lucas(sum+n-1,n-1)+MOD)%MOD;
        }
        printf("%lld\n",(ans+MOD)%MOD);
    }
    return 0;
}


在26号凌晨终于写完该24号写的博客,明天将这个题目再吸收下>.<,补校赛题,两篇博客,加油呀!



                                                                                                                                                                  --------------2018/1/26

猜你喜欢

转载自blog.csdn.net/qq_38144740/article/details/79156824