链接
题意:
有 2 n 2n 2n 个桶
第 2 x − 1 2x − 1 2x−1 个桶可以拿 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})
(0−2i)然后我们乍一看并没有找出其中的关系,比较难理解,既然我们发现 奇数位置是成倍数增加 ,而偶数位置是一个单位内范围增加减少,那么我们把这两个位置当成一个位置来看会怎么样那。
那么当我们在这两个位置 ( 2 x − 1 , 2 x ) (2x-1,2x) (2x−1,2x)里面一共取 y y y个球,那么a*x+z=y;分为两种情况:
- z ! = 0 z!=0 z!=0那么z一定取自偶数(2x)位置中, a ∗ x a*x a∗x一定取自(2x-1)这个位置。原因因该很好理解.
-
z
=
0
z=0
z=0那么
2
x
2x
2x位置可以取x也可以取0个,
这样俩种情况我们发现非常难分析,那么我们直接把x=0这种情况提取出来不就好了,先每个偶数位置上取值范围变成 [ 0 , x − 1 ] [0,x-1] [0,x−1]这样比挺好的,然后将 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 m−i个球,这就是典型的插板,箱子可以为0。那么方案数是 C m − i + n − 1 n − 1 C_{m-i+n-1}^{n-1} Cm−i+n−1n−1
然后总和为:
∑
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=0∑nCm−i+n−1n−1=Cm+n−1n−1+Cm+n−2n−1+...+Cm−1n−1
怎么求解那?我们先看组合数的性质:
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=Cm−1n+Cm−1n−1
那么我们在上面那个式子后面加上
C
m
−
1
n
C_{m-1}^{n}
Cm−1n再减去
C
m
−
1
n
C_{m-1}^{n}
Cm−1n那么结果会变成什么那:
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+n−1n−1+Cm+n−2n−1+...+Cm−1n−1+Cm−1n−Cm−1n
我们会发现
C
m
−
1
n
−
1
+
C
m
−
1
n
=
C
m
n
C _{m-1}^{n-1}+C_{m-1}^{n}=C_m^n
Cm−1n−1+Cm−1n=Cmn这样依次向上找到最后结果就是:
C m + n n − C m − 1 n C_{m+n}^{n}-C_{m-1}^{n} Cm+nn−Cm−1n
#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;
}