题目
口袋里有
c
c
c种颜色的巧克力。从中随便取出一个。若桌上有与它颜色相同的巧克力,则两个都拿走;否则将它放在桌子上。求拿出
n
n
n个后桌子上剩
m
m
m个的概率。
数据范围:
1
≤
c
≤
100
,
n
,
m
≤
1000000
1≤c≤100,n,m≤1000000
1≤c≤100,n,m≤1000000
思路
- 易得:n,m奇偶性相同
- m ≤ c , n m≤c,n m≤c,n
设计
设有
a
a
a种巧克力取了奇数次,则有
c
−
a
c-a
c−a种取了偶数次。
考虑到,若是使用普通生成函数的话,因为结果有除掉
k
!
k!
k!,所以是不好做的,这个时候,我们就选择使用指数型生成函数(EGF)。
奇数次的生成函数:
J
(
x
)
=
x
1
!
+
x
3
3
!
+
x
5
5
!
+
.
.
.
J(x)=\frac{x}{1!}+\frac{x^3}{3!}+\frac{x^5}{5!}+...
J(x)=1!x+3!x3+5!x5+...
偶数次的生成函数:
O
(
x
)
=
1
+
x
2
2
!
+
x
4
4
!
+
.
.
.
O(x)=1+\frac{x^2}{2!}+\frac{x^4}{4!}+...
O(x)=1+2!x2+4!x4+...
设答案多项式为
H
(
x
)
H(x)
H(x),有:
H
(
x
)
=
C
c
a
×
J
(
x
)
a
×
O
(
x
)
c
−
a
H(x)=C_{c}^{a}\times J(x)^a\times O(x)^{c-a}
H(x)=Cca×J(x)a×O(x)c−a
H
(
x
)
H(x)
H(x)的第
n
n
n项前的系数就是合法的组合的方案数
转化
设
f
(
x
)
=
e
x
f(x)=e^x
f(x)=ex,对
f
(
x
)
f(x)
f(x)在零点处进行泰勒展开。
f
(
x
)
=
f
(
x
0
)
+
f
′
(
0
)
1
!
x
+
f
′
′
(
0
)
2
!
x
2
+
.
.
.
f(x)=f(x_0)+\frac{f'(0)}{1!}x+\frac{f''(0)}{2!}x^2+...
f(x)=f(x0)+1!f′(0)x+2!f′′(0)x2+...
因为
e
x
=
e
′
x
e^x=e'^x
ex=e′x
所以
f
(
x
)
=
f
′
(
x
)
f(x)=f'(x)
f(x)=f′(x)
上式可化为
f
(
x
)
=
1
+
x
1
!
+
x
2
2
!
+
x
3
3
!
+
x
4
4
!
+
.
.
.
f(x)=1+\frac{x}{1!}+\frac{x^2}{2!}+\frac{x^3}{3!}+\frac{x^4}{4!}+...
f(x)=1+1!x+2!x2+3!x3+4!x4+...
f
(
−
x
)
=
1
−
x
1
!
+
x
2
2
!
−
x
3
3
!
+
x
4
4
!
+
.
.
.
f(-x)=1-\frac{x}{1!}+\frac{x^2}{2!}-\frac{x^3}{3!}+\frac{x^4}{4!}+...
f(−x)=1−1!x+2!x2−3!x3+4!x4+...
所以
e
x
=
1
+
x
1
!
+
x
2
2
!
+
x
3
3
!
+
x
4
4
!
+
.
.
.
e^x=1+\frac{x}{1!}+\frac{x^2}{2!}+\frac{x^3}{3!}+\frac{x^4}{4!}+...
ex=1+1!x+2!x2+3!x3+4!x4+...
e
−
x
=
1
−
x
1
!
+
x
2
2
!
−
x
3
3
!
+
x
4
4
!
+
.
.
.
e^{-x}=1-\frac{x}{1!}+\frac{x^2}{2!}-\frac{x^3}{3!}+\frac{x^4}{4!}+...
e−x=1−1!x+2!x2−3!x3+4!x4+...
e
x
−
e
−
x
=
2
x
1
!
+
2
x
3
3
!
+
.
.
.
2
x
5
5
!
e^x-e^{-x}=2\frac{x}{1!}+2\frac{x^3}{3!}+...2\frac{x^5}{5!}
ex−e−x=21!x+23!x3+...25!x5
e
x
+
e
−
x
=
2
+
2
x
2
2
!
+
2
x
4
4
!
+
.
.
.
e^x+e^{-x}=2+2\frac{x^2}{2!}+2\frac{x^4}{4!}+...
ex+e−x=2+22!x2+24!x4+...
所以奇数次的生成函数的闭形式为:
e
x
−
e
−
x
2
\frac{e^x-e^{-x}}{2}
2ex−e−x
偶数次的生成函数的闭形式为:
e
x
+
e
−
x
2
\frac{e^x+e^{-x}}{2}
2ex+e−x
化简
由上可得:
H
(
x
)
=
C
c
a
×
J
(
x
)
a
×
O
(
x
)
c
−
a
=
(
e
x
−
e
−
x
2
)
a
×
(
e
x
+
e
−
x
2
)
c
−
a
H(x)=C_{c}^{a}\times J(x)^a\times O(x)^{c-a}=(\frac{e^x-e^{-x}}{2})^a\times (\frac{e^x+e^{-x}}{2})^{c-a}
H(x)=Cca×J(x)a×O(x)c−a=(2ex−e−x)a×(2ex+e−x)c−a
进行二项式展开:
H
(
x
)
=
2
−
c
×
C
c
a
×
∑
i
=
0
a
−
1
i
×
C
a
i
×
e
a
−
2
i
x
×
∑
j
=
0
c
−
a
C
c
−
m
j
×
e
c
−
a
−
2
j
H(x)=2^{-c}\times C_{c}^{a}\times \sum_{i=0}^{a}{-1}^i\times C_{a}^{i}\times e^{a-2i}x\times \sum_{j=0}^{c-a}C_{c-m}^{j}\times e^{c-a-2j}
H(x)=2−c×Cca×i=0∑a−1i×Cai×ea−2ix×j=0∑c−aCc−mj×ec−a−2j
写成卷积:
H
(
x
)
=
2
−
c
×
C
c
a
×
∑
i
=
0
a
∑
j
=
0
c
−
a
−
1
i
×
C
a
i
×
C
c
−
m
j
×
e
c
−
2
i
−
2
j
x
H(x)=2^{-c}\times C_{c}^{a}\times \sum_{i=0}^{a}\sum_{j=0}^{c-a}{-1}^i\times C_{a}^{i}\times C_{c-m}^{j}\times e^{c-2i-2j}x
H(x)=2−c×Cca×i=0∑aj=0∑c−a−1i×Cai×Cc−mj×ec−2i−2jx
把
e
e
e换掉
H
(
x
)
=
2
−
c
×
C
c
a
×
∑
i
=
0
a
∑
j
=
0
c
−
a
−
1
i
×
C
a
i
×
C
c
−
m
j
×
∑
k
=
0
+
∞
(
(
c
−
2
i
−
2
j
)
x
)
k
k
!
H(x)=2^{-c}\times C_{c}^{a}\times \sum_{i=0}^{a}\sum_{j=0}^{c-a}{-1}^i\times C_{a}^{i}\times C_{c-m}^{j}\times \sum_{k=0}^{+\infty}\frac{(({c-2i-2j})x)^k}{k!}
H(x)=2−c×Cca×i=0∑aj=0∑c−a−1i×Cai×Cc−mj×k=0∑+∞k!((c−2i−2j)x)k
所以
h
n
=
2
−
c
×
C
c
a
×
∑
i
=
0
a
∑
j
=
0
c
−
a
−
1
i
×
C
a
i
×
C
c
−
m
j
×
(
c
−
2
i
−
2
j
)
n
n
!
h_n=2^{-c}\times C_{c}^{a}\times \sum_{i=0}^{a}\sum_{j=0}^{c-a}{-1}^i\times C_{a}^{i}\times C_{c-m}^{j}\times \frac{(c-2i-2j)^n}{n!}
hn=2−c×Cca×i=0∑aj=0∑c−a−1i×Cai×Cc−mj×n!(c−2i−2j)n
得到答案
上面的
h
n
h_n
hn是合法的组合的方案数,因为颜色是有顺序的,所以还要乘上一个
n
!
n!
n!。而总方案数为
c
n
c^n
cn
所以最后的
A
n
s
Ans
Ans为:
h
n
∗
n
!
c
n
\frac{h_n*n!}{c^n}
cnhn∗n!
因为
1
≤
c
≤
100
1≤c≤100
1≤c≤100,
2
c
2^c
2c会乘爆,只能用
d
o
u
b
l
e
double
double乘一下,用精度换数值正确。
把除放在最后,避免精度误差。
Code:
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define DB double
#define MAXN 105
#define LL long long
#define Int register int
using namespace std;
inline int read()
{
int x = 0, f = 1;
char s = getchar();
while (s < '0' || s > '9')
{
if (s == '-')
f = -1;
s = getchar();
}
while (s >= '0' && s <= '9')
{
x = (x << 3) + (x << 1) + (s ^ 48);
s = getchar();
}
return x * f;
}
inline int Max(int x,int y)
{
return x > y ? x : y;
}
inline int Min(int x,int y)
{
return x < y ? x : y;
}
inline DB QuickPow(DB x,int y)
{
DB Res = 1, temp = x;
while ( y )
{
if (y & 1)
Res *= temp;
temp *= temp;
y /= 2;
}
return Res;
}
DB C[MAXN][MAXN];
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 (~ scanf("%d %d %d", &c, &n, &m) && c)
{
if (m > c || m > n || (n - m) & 1)
{
printf("0.000\n");
continue;
}
DB fuck = 0;
for (Int i = 0; i <= m; ++ i)
for (Int j = 0; j <= c - m; ++ j)
fuck += ((i & 1) ? -1 : 1) * C[m][i] * C[c - m][j] * QuickPow((c - 2 * i - 2 * j) * 1.0 / c, n);
fuck *= C[c][m];
fuck /= QuickPow(2.0, c);
printf("%.3lf\n", fuck);
}
return 0;
}