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

题意:给你n对桶,第i对能分别提供出来0,1,2,...,i-1个球以及0,i,2i,3i,...个球,问凑m个球的方案数

第i对的生成函数为

\[\rm (1+x+x^2+...+x^i)(1+x^i+x^{2i}+...) \]

等比数列求和有

\[\dfrac{x^{i+1}-1}{x-1}\times \dfrac{1}{1-x^i} \]

考虑生成函数的实际意义,把n个生成函数乘起来,答案就是\(x^m\)的系数

\[\prod\limits_{i=2}^{n+1}\dfrac{x^i-1}{x-1}\prod\limits_{i=1}^{n}{\dfrac{1}{1-x^i}} \]

抽出来前面的n+1项和后面的第1项,有

\[\dfrac{x^{n+1}-1}{x-1}\times \dfrac{1}{x-1}(-1)^n\prod\limits_{i=2}^{n}\dfrac{x^i-1}{x-1}\dfrac{1}{x^i-1} \]

后面都被干掉了,把下面的1+1+(n-1)个(x-1)合并起来有

\[(-1)^n\dfrac{x^{n+1}-1}{(x-1)^{n+1}} \]

把分母用广义二项式定理展开有

\[(-1)^n(x^{n+1}-1)\sum\limits_{k=0}^\infty \mathbf{C}_{-(n+1)}^{k}(-1)^kx^k(-1)^{-(n+1)-k} \]

对组合数做负指标变换

\[(-1)^n(x^{n+1}-1)\sum\limits_{k=0}^\infty \mathbf{C}_{k+(n+1)-1}^{k}(-1)^kx^k(-1)^{-(n+1)-k} \]

合并一下(-1)的指数,发现能提出来,和前面的合并

\[(1-x^{n+1})\sum\limits_{k=0}^\infty \mathbf{C}_{k+n}^kx^k \]

至此可以做了,我们要找\(x^m\)的系数

首先令k=m,得到\(\mathbf{C}_{m+n}^m\)

然后令k=m-(n+1),得到\(-\mathbf{C}_{m-1}^{m-(n+1)}\),也即\(-\mathbf{C}_{m-1}^{n}\)

注意前面有个负号

最终答案为\(\mathbf{C}_{m+n}^m - \mathbf{C}_{m-1}^n\)

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int MOD = 1e9+7;
const int MAXN = 2000006;

int fac[MAXN];
int inv[MAXN];

int qpow(int x,int y=MOD-2){
  int ret=1,base=x;
  while(y){
    if(y&1) ret=ret*base%MOD;
    base=base*base%MOD;
    y>>=1;
  }
  return ret;
}

int c(int x,int y){
  if(x<y) return 0;
  return fac[x]*inv[y]%MOD*inv[x-y]%MOD;
}

signed main(){
  fac[0]=1;
  for(int i=1;i<=2000000;i++)
    fac[i]=fac[i-1]*i%MOD;
  inv[2000000]=qpow(fac[2000000]);
  for(int i=2000000-1;i>=1;i--)
    inv[i]=inv[i+1]*(i+1)%MOD;
  int T;
  cin>>T;
  while(T--){
    int n,m;
    cin>>n>>m;
    cout<<(c(n+m,m)-c(m-1,n)+MOD)%MOD<<endl;
  }
}
posted @ 2021-08-10 19:32  GhostCai  阅读(61)  评论(0编辑  收藏  举报