题目
一个口袋中装有巧克力,巧克力的颜色有
c
c
c 种。现从口袋中取出一个巧克力,若取出的
巧克力与桌上某一已有巧克力颜色相同,则将两个巧克力都取走,否则将取出的巧克力放在桌上。设从口袋中取出每种颜色的巧克力的概率均等。求取出
n
n
n 个巧克力后桌面上剩余
m
m
m 个巧克力的概率。
数据范围:
1
≤
c
≤
100
,
n
,
m
≤
1000000
1\le c\le 100,n,m\le1000000
1≤c≤100,n,m≤1000000
思路
我们首先考虑数据的合法性:
a.
n
,
m
同
奇
偶
n,m同奇偶
n,m同奇偶
b.
m
<
=
n
a
n
d
m
<
=
c
m<=n\quad and \quad m<=c
m<=nandm<=c
那么我们可以发现
n
−
m
n-m
n−m 为
2
2
2 的倍数,那么剩下的
m
m
m 颗意味着有
m
m
m 种巧克力是取了奇数次,那我们就要确定到底是哪几种
然后我们考虑母函数表示
G
(
x
)
=
C
c
m
∗
(
e
x
−
e
−
x
2
)
m
∗
(
e
x
+
e
−
x
2
)
c
−
m
G(x)=C_c^m*(\frac{e^x-e^{-x}}{2})^m*(\frac{e^x+e^{-x}}{2})^{c-m}
G(x)=Ccm∗(2ex−e−x)m∗(2ex+e−x)c−m
解释一下,这表示我们首先确定取奇数的方案数
C
c
m
C_c^m
Ccm 然后由于取巧克力有顺序要求,所以我们考虑指数型母函数
于是我们要确定第
n
n
n 项的系数
我们将
e
x
e^x
ex 保留进行还原多项式:
G
(
x
)
=
2
−
c
∗
C
c
m
∗
(
e
x
−
e
−
x
)
m
∗
(
e
x
+
e
−
x
)
c
−
m
G(x)=2^{-c}*C_c^m*(e^x-e^{-x})^m*(e^x+e^{-x})^{c-m}
G(x)=2−c∗Ccm∗(ex−e−x)m∗(ex+e−x)c−m
G
(
x
)
=
2
−
c
∗
C
c
m
∗
∑
i
=
0
m
(
−
1
)
i
∗
C
m
i
∗
e
(
m
−
2
i
)
x
∗
∑
j
=
0
c
−
m
C
c
−
m
j
∗
e
(
c
−
m
−
2
j
)
x
G(x)=2^{-c}*C_c^m*\sum_{i=0}^m(-1)^i*C_m^i*e^{(m-2i)x}* \sum_{j=0}^{c-m}C_{c-m}^j*e^{(c-m-2j)x}
G(x)=2−c∗Ccm∗i=0∑m(−1)i∗Cmi∗e(m−2i)x∗j=0∑c−mCc−mj∗e(c−m−2j)x
G
(
x
)
=
2
−
c
∗
C
c
m
∗
∑
i
=
0
m
∑
j
=
0
c
−
m
(
−
1
)
i
∗
C
m
i
C
c
−
m
j
∗
e
(
c
−
2
i
−
2
j
)
x
G(x)=2^{-c}*C_c^m*\sum_{i=0}^m\sum_{j=0}^{c-m}(-1)^i*C_m^iC_{c-m}^j*e^{(c-2i-2j)x}
G(x)=2−c∗Ccm∗i=0∑mj=0∑c−m(−1)i∗CmiCc−mj∗e(c−2i−2j)x
G
(
x
)
=
2
−
c
∗
C
c
m
∗
∑
i
=
0
m
∑
j
=
0
c
−
m
(
−
1
)
i
∗
C
m
i
C
c
−
m
j
∗
∑
k
=
0
+
∞
(
(
c
−
2
i
−
2
j
)
x
)
k
k
!
G(x)=2^{-c}*C_c^m*\sum_{i=0}^m\sum_{j=0}^{c-m}(-1)^i*C_m^iC_{c-m}^j*\sum_{k=0}^{+\infty}\frac{((c-2i-2j)x)^k}{k!}
G(x)=2−c∗Ccm∗i=0∑mj=0∑c−m(−1)i∗CmiCc−mj∗k=0∑+∞k!((c−2i−2j)x)k
那么第n项的系数
a
n
a_n
an 为:
a
n
=
2
−
c
∗
C
c
m
∗
∑
i
=
0
m
∑
j
=
0
c
−
m
(
−
1
)
i
∗
C
m
i
C
c
−
m
j
∗
(
c
−
2
i
−
2
j
)
n
n
!
a_n=2^{-c}*C_c^m*\sum_{i=0}^m\sum_{j=0}^{c-m}(-1)^i*C_m^iC_{c-m}^j*\frac{(c-2i-2j)^n}{n!}
an=2−c∗Ccm∗i=0∑mj=0∑c−m(−1)i∗CmiCc−mj∗n!(c−2i−2j)n
所以符合条件的方案数为
a
n
∗
n
!
a_n*n!
an∗n! ,我们发现总方案数为:
c
n
c^n
cn
所以概率为:
a
n
∗
n
!
c
n
\frac{a_n*n!}{c^n}
cnan∗n!
注意,尽量将除法放在最后减小精度误差
代码
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<ctime>
#include<bitset>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
#define ULL unsigned long long
int read(){
int f=1,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return f*x;
}
#define MAXN 100
#define INF 0x3f3f3f3f
double Pow(double x,int y){
double ret=1.0;
while(y){
if(y&1) ret*=x;
x*=x;
y>>=1;
}
return ret;
}
double C[MAXN+5][MAXN+5];
void Prepare(){
C[0][0]=1;
for(int i=1;i<=MAXN;i++){
C[i][0]=1;
for(int j=1;j<=i;j++)
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
return ;
}
int main(){
int c,n,m;
Prepare();
while(1){
c=read();
if(!c) break;
n=read(),m=read();
if(m>c||m>n||(n-m)%2){
puts("0.000");
continue;
}
double ans=0;
for(int i=0;i<=m;i++)
for(int j=0;j<=c-m;j++)
ans+=((i&1)?-1:1)*C[m][i]*C[c-m][j]*Pow((c-2*i-2*j)*1.0/c,n);
ans=ans*C[c][m]/Pow(2,c);
printf("%f\n",ans);
}
return 0;
}