HDU -7047 Link with Balls(组合数学)

链接

题意:

2 n 2n 2n 个桶

2 x − 1 2x − 1 2x1 个桶可以拿 k x k x kx 个球( k > = 0 k > = 0 k>=0

2 x 2x 2x 个桶最多拿 x x x个球

求拿取 m m m个球的方案数

分析:

题意有点难懂,虾米题意把朕都搞蒙圈了
虽然比较艰难,但是还是可以懂的,赛场上遇见这种也只能细心读下去,抱怨并没有*用

进入正题:乐式讲解法show Time:
首先我们看题意:无非就是奇数位置可以取 k ( i + 1 ) 2 ( k > = 0 ) \frac{k(i+1)}{2}(k>=0) 2k(i+1)(k>=0)偶数可以取 ( 0 − i 2 ) (0-\frac{i}{2}) (02i)然后我们乍一看并没有找出其中的关系,比较难理解,既然我们发现 奇数位置是成倍数增加 ,而偶数位置是一个单位内范围增加减少,那么我们把这两个位置当成一个位置来看会怎么样那。

那么当我们在这两个位置 ( 2 x − 1 , 2 x ) (2x-1,2x) (2x1,2x)里面一共取 y y y个球,那么a*x+z=y;分为两种情况:

  • z ! = 0 z!=0 z!=0那么z一定取自偶数(2x)位置中, a ∗ x a*x ax一定取自(2x-1)这个位置。原因因该很好理解.
  • z = 0 z=0 z=0那么 2 x 2x 2x位置可以取x也可以取0个,
    这样俩种情况我们发现非常难分析,那么我们直接把x=0这种情况提取出来不就好了,先每个偶数位置上取值范围变成 [ 0 , x − 1 ] [0,x-1] [0,x1]这样比挺好的,然后将 2 n 2n 2n个箱子变成 n n n个取值范围为 0 , 无 穷 大 0,无穷大 0,再加上一个取值范围为 [ 0 , n ] [0,n] [0,n]的箱子(我们在每个偶数位置提取出来的)。
    这样看就很好分析了,一共m个球,我们可以先放进 [ 0 , n ] [0,n] [0,n]箱子 i i i个那么剩下n个箱子分 m − i m-i mi个球,这就是典型的插板,箱子可以为0。那么方案数是 C m − i + n − 1 n − 1 C_{m-i+n-1}^{n-1} Cmi+n1n1

然后总和为:
∑ i = 0 n C m − i + n − 1 n − 1 = C m + n − 1 n − 1 + C m + n − 2 n − 1 + . . . + C m − 1 n − 1 \sum_{i=0}^{n} C_{m-i+n-1}^{n-1}=C _{m+n-1}^{n-1}+C _{m+n-2}^{n-1}+...+C _{m-1}^{n-1} i=0nCmi+n1n1=Cm+n1n1+Cm+n2n1+...+Cm1n1

怎么求解那?我们先看组合数的性质:
C m n = C m − 1 n + C m − 1 n − 1 C_m^n=C_{m-1}^n+C_{m-1}^{n-1} Cmn=Cm1n+Cm1n1
那么我们在上面那个式子后面加上 C m − 1 n C_{m-1}^{n} Cm1n再减去 C m − 1 n C_{m-1}^{n} Cm1n那么结果会变成什么那:
C m + n − 1 n − 1 + C m + n − 2 n − 1 + . . . + C m − 1 n − 1 + C m − 1 n − C m − 1 n C _{m+n-1}^{n-1}+C _{m+n-2}^{n-1}+...+C _{m-1}^{n-1}+C_{m-1}^{n}-C_{m-1}^{n} Cm+n1n1+Cm+n2n1+...+Cm1n1+Cm1nCm1n
我们会发现 C m − 1 n − 1 + C m − 1 n = C m n C _{m-1}^{n-1}+C_{m-1}^{n}=C_m^n Cm1n1+Cm1n=Cmn这样依次向上找到最后结果就是:

C m + n n − C m − 1 n C_{m+n}^{n}-C_{m-1}^{n} Cm+nnCm1n

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e6 + 7;
#define ll long long
#define x first
#define y second
#define pii pair<int ,int >
const int mod = 1e9 + 7;

ll qpow(ll a, ll b, ll p)
{
    ll ans = 1;
    while (b)
    {
        if(b & 1) ans = ans * a % p;
        b >>= 1;
        a = a * a % p;
    }
    return ans;
}
ll infac[maxn], fac[maxn];
void init()
{
    fac[0] = 1;
    fac[1] = 1;
    infac[0] = 1;
    for(ll i = 1; i < maxn; i++)
    {
        fac[i] = i * fac[i - 1] % mod;
        infac[i] = infac[i - 1] * qpow(i, mod - 2, mod) % mod;
    }
}
ll C(ll n, ll m)
{
    if(n < m) return 0;
    return fac[n] * infac[m] % mod * infac[n - m] % mod;
}

void solve()
{
    ll n, m;
    scanf("%lld%lld", &n, &m);
    printf("%lld\n", (C(n + m, n) - C(m - 1, n) + mod) % mod);
}

int main()
{
    init();
    int t = 1;
    scanf("%d", &t);
    while(t--)
    {
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值