中超7 hdu 7047 Link with Balls (生成函数板子)

53 篇文章 0 订阅
44 篇文章 0 订阅

2021“MINIEYE杯”中国大学生算法设计超级联赛(7)

hdu 7047 Link with Balls

题意:

(这个题面就离谱,看老半天)

  • 2 n 2n 2n 个桶

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

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

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

复盘:

(赛时觉得是组合数学,但这变化是真的难以操作,赛后看了大佬的题解发现是还没学的生成函数的板子题)

不会生成函数的先看这篇:这可能是最通俗最详细的生成函数讲解了吧!!!

O r z 大 佬 i s s u e Orz大佬issue Orzissue ,看了大佬的博客,我就入门了生成函数
f ( 2 u − 1 ) = 1 + x u + x 2 u + x 3 u + . . . = 1 1 − x u \begin{aligned} f(2u-1) &= 1+x^u+x^{2u}+x^{3u}+...\\ &=\frac{1}{1-x^u} \end{aligned} f(2u1)=1+xu+x2u+x3u+...=1xu1

f ( 2 u ) = 1 + x + x 2 + x 3 + . . . + x u = 1 − x u + 1 1 − x \begin{aligned} f(2u) &= 1+x+x^{2}+x^{3}+...+x^u\\ &=\frac{1-x^{u+1}}{1-x} \end {aligned} f(2u)=1+x+x2+x3+...+xu=1x1xu+1
总的生成函数即为:
∏ i = 1 2 n f i = ( 1 1 − x 1 1 − x 2 1 1 − x 3 . . . 1 1 − x n ) ( 1 − x 2 1 − x 1 − x 3 1 − x 1 − x 4 1 − x . . . 1 − x n + 1 1 − x ) = 1 − x n + 1 ( 1 − x ) n + 1 = ( 1 − x n + 1 ) ( 1 − x ) − ( n + 1 ) \begin{aligned} \prod_{i=1}^{2n}{f_i} &= (\frac{1}{1-x}\frac{1}{1-x^2}\frac{1}{1-x^3}...\frac{1}{1-x^n})(\frac{1-x^2}{1-x}\frac{1-x^3}{1-x}\frac{1-x^4}{1-x}...\frac{1-x^{n+1}}{1-x}) \\ &=\frac{1-x^{n+1}}{(1-x)^{n+1}}\\ &=(1-x^{n+1})(1-x)^{-(n+1)} \end{aligned} i=12nfi=(1x11x211x31...1xn1)(1x1x21x1x31x1x4...1x1xn+1)=(1x)n+11xn+1=(1xn+1)(1x)(n+1)

最后我们要求的就是 x m x^m xm 的系数(令其为 [ x m ] [x_m] [xm]):

多项式指数为负数时: ( 1 − x ) − n 的 [ x m ] = ( m n + m − 1 ) 式 1 = ( n − 1 n + m − 1 ) 式 2 (1-x)^{-n}的[x_m]=(_{m}^{n+m-1})_{式1}=(_{n-1}^{n+m-1})_{式2} (1x)n[xm]=(mn+m1)1=(n1n+m1)2

由于m有可能大于n,故我们用式2,即为: ( n n + m ) − ( n m − 1 ) (_{n}^{n+m})-(_{n}^{m-1}) (nn+m)(nm1)

若用式1: ( m n + m ) − ( m m − 1 ) (_{m}^{n+m})-(_{m}^{m-1}) (mn+m)(mm1) ,减数永远为0,会出错

接下来就是套 C n m C_n^m Cnm 的板子了

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5, mo=1e9+7;

int fac[N*2], inv[N*2];
void init(int n)
{
    fac[0] = 1;
    for(int i=1;i<=n;i++) fac[i] = 1LL*fac[i-1]*i%mo;
    inv[0] = inv[1] = 1;
    for(int i=2;i<=n;i++) inv[i] = mo - 1LL*(mo/i)*inv[mo%i]%mo;
    for(int i=2;i<=n;i++) inv[i] = 1LL*inv[i-1]*inv[i]%mo;
}
inline int C(int n, int m)
{
    if(n<0 || m>n) return 0;
    return 1LL*fac[n]*inv[m]%mo*inv[n-m]%mo;
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
    int t;
    cin>>t;
    init((int)2e6);
    while(t--)
    {
        int n,m;
        cin>>n>>m;
        int ans= (C(n+m,n)-C(m-1,n)+mo)%mo;
        cout<<ans<<endl;
    }

    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yezzz.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值