组合
一道组合数学题,做得很蛋疼,仿佛回到了高中数竞的生活(qaq), 链接
http://acm.fzu.edu.cn/problem.php?pid=2303
解析
题目的意思很简单,把m个cake分给n个person, 每个person最多能拿一个cake, 然后这些person是有继承关系的,即这个人拿到蛋糕后,你能得到的信任是这个人以及它所有的子结点的值,求你能得到的值的期望。显然,当
m
≥
n
m \geq n
m≥n时,由鸽巢原理知,最后一个peron至少能拿到一个cake,所以总的值为n,当
m
<
n
m<n
m<n时呢?显然你也知道了,决定权都会在最后一个手上,因为这个person拿了cake,那么你就能得到他的所有子结点的值。那么我们只要关注cake分到的最后一个person就好了。
所有的方案数
C
n
m
C_{n}^{m}
Cnm,对于长度
i
i
i, 我们指定第
i
i
i个person拿一个cake,剩下的cake分给
i
−
1
i-1
i−1个person即可,那么总的方案数为:
∑
i
=
m
n
i
⋅
C
i
−
1
m
−
1
\sum_{i=m}^{n} i\cdot C_{i-1}^{m-1}
i=m∑ni⋅Ci−1m−1答案为
a
n
s
=
∑
i
=
m
n
i
⋅
C
i
−
1
m
−
1
C
n
m
ans=\frac{\sum_{i=m}^{n} i\cdot C_{i-1}^{m-1}}{C_{n}^{m}}
ans=Cnm∑i=mni⋅Ci−1m−1这样貌似做出来,但突然发现
n
,
m
≤
1000000
n,m\leq 1000000
n,m≤1000000,这个数据范围,3秒也无能为力的,所以我们尝试对分子进行化简下
i
⋅
C
i
−
1
m
−
1
=
i
⋅
(
i
−
1
)
!
(
m
−
1
)
!
(
i
−
m
)
!
=
m
⋅
i
!
m
!
(
i
−
m
)
!
=
m
⋅
C
i
m
i \cdot C_{i-1}^{m-1}=\frac{i \cdot (i-1)!}{(m-1)!(i-m)!}=\frac{m \cdot i!}{m!(i-m)!}=m\cdot C_{i}^{m}
i⋅Ci−1m−1=(m−1)!(i−m)!i⋅(i−1)!=m!(i−m)!m⋅i!=m⋅Cim有点眉目了,但好像还是不能做的样子(qaq)。所以还是得仔细研究下,显然这个组合数的取数是固定的,而总的数是在增加的,所以尝试研究下这里面有什么关系
C
n
+
1
k
=
(
n
+
1
)
!
k
!
(
n
+
1
−
k
)
!
=
(
n
+
1
)
⋅
n
!
(
n
+
1
−
k
)
⋅
k
!
(
n
−
k
)
!
=
(
1
+
k
n
+
1
−
k
)
C
n
k
C_{n+1}^{k}=\frac{(n+1)!}{k!(n+1-k)!}=\frac{(n+1)\cdot n!}{(n+1-k)\cdot k!(n-k)!}=(1+\frac{k}{n+1-k})C_{n}^{k}
Cn+1k=k!(n+1−k)!(n+1)!=(n+1−k)⋅k!(n−k)!(n+1)⋅n!=(1+n+1−kk)Cnk然后移项下有
C
n
+
1
k
−
C
n
k
=
k
n
+
1
−
k
C
n
k
=
C
n
k
−
1
C_{n+1}^{k}-C_{n}^{k}=\frac{k}{n+1-k}C_{n}^{k}=C_{n}^{k-1}
Cn+1k−Cnk=n+1−kkCnk=Cnk−1是不是看出什么猫腻了(hahaha),我们将上述式子构造
n
n
n个相加
C
1
k
−
C
0
k
=
C
0
k
−
1
C_{1}^{k}-C_{0}^{k}=C_{0}^{k-1}
C1k−C0k=C0k−1
C
2
k
−
C
1
k
=
C
1
k
−
1
C_{2}^{k}-C_{1}^{k}=C_{1}^{k-1}
C2k−C1k=C1k−1
⋮
\vdots
⋮
C
n
+
1
k
−
C
n
k
=
C
n
k
−
1
C_{n+1}^{k}-C_{n}^{k}=C_{n}^{k-1}
Cn+1k−Cnk=Cnk−1可得
C
n
+
1
k
=
∑
i
=
0
n
C
i
k
−
1
C_{n+1}^{k}=\sum_{i=0}^{n}C_{i}^{k-1}
Cn+1k=∑i=0nCik−1
那么只要预处理下阶乘答案就行了。(不知道为什么我交了还是超时,可能是输入输出太多了,所以该用Fast-IO就AC了)
AC代码
/*
小学生一发的刷题之路;
今天你刷题了吗???
*/
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <vector>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI=acos(-1.0);
const int maxn=1e6+5;
const ll mod=1e9+7;
template<class T>
inline void read(T &ret){ //快速输入模版;
ret=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
ret=ret*10+c-'0';
c=getchar();
}
ret*=f;
}
template <class T>
inline void out(T ret){ //快速输出模版;
if(ret>9)
{
out(ret/10);
}
putchar(ret%10+'0');
}
ll A[maxn],Amod[maxn];
ll poww(ll a,ll b){
ll ans=1,base=a;
while(b){
if(b&1){
ans*=base;
ans%=mod;
}
b>>=1;
base*=base;
base%=mod;
}
return ans;
}
void init(){
A[0]=1;
Amod[0]=1;
for(int i=1;i<=1e6+1;i++){
A[i]=A[i-1]*i;
A[i]%=mod;
Amod[i]=poww(A[i],mod-2);
}
}
int main(){
init();
int t,n,m;
scanf("%d",&t);
while(t--){
read(n);
read(m);
if(m>=n){
out(n);
puts("");
continue;
}else{
ll num=((A[n]*Amod[m])%mod*A[n-m])%mod;
ll ans=((A[n+1]*Amod[m+1])%mod*A[n-m])%mod;
ans=(ans*m)%mod;
ans=(ans*poww(num,mod-2))%mod;
out(ans);
puts("");
}
}
return 0;
}
新的开始,每天都要快乐哈!