题目大意:把n个桃子给m个不同的猴子,第一个必须拿严格最多,求方案数
具体思路:首先考虑没有限制的情况,好像插个隔板就好了呢
然后我们可以枚举第一个猴子的拿桃数,
于是我们可以求出第一个猴子的拿桃数已知的总方案
然后减去不合法的就好了
怎么减勒?我们枚举有几个猴子拿的桃比大王多,然后用组合数求出有几种取法,在一顿乱搞就好了
于是貌似重复了耶,结果发现如果有两个猴子拿的桃比大王多,这个情况会被在前面算2次,那么我们减掉
如果有三个猴子拿的桃比大王多,这个情况会被在前面算0次,我们把它加上
...
于是从1开始一个加一个减就好了(不会证)
AC代码
#include<bits/stdc++.h> using namespace std; #define int long long const int ha=1000000007; int n,m,fact[200010],factinv[200010],inv[200010],ans,T; int INV(int x) { int ans=1,b=ha-2,a=x; while (b) { if(b&1)ans=ans*a%ha; b=b/2;a=a*a%ha; } return ans; } int C(int x,int y){return fact[x]*factinv[y]%ha*factinv[x-y]%ha;} int F(int x,int y){return C(x+y-1,y-1);} signed main() { fact[0]=1,factinv[0]=1,scanf("%lld",&T); for (register int i=1;i<=200000;i++)fact[i]=fact[i-1]*i%ha,inv[i]=INV(i),factinv[i]=factinv[i-1]*inv[i]%ha; while(T--) { scanf("%lld%lld",&n,&m),ans=F(n,m); for (register int i=0;i<=n;i++) for (register int j=1;j<=m&&i*(j+1)<=n;j++)(j%2)?ans=(ans-C(m-1,j)*F(n-i*(j+1),m-1)%ha+ha)%ha:ans=(ans+C(m-1,j)*F(n-i*(j+1),m-1)%ha)%ha; printf("%lld\n",ans); } return 0; }