Chocolate

一、题目

题目描述
一个口袋中装有巧克力,巧克力的颜色有 c c 种。现从口袋中取出一个巧克力,若取出的巧克力与桌上某一已有巧克力颜色相同,则将两个巧克力都取走,否则将取出的巧克力放在桌上。设从口袋中取出每种颜色的巧克力的概率均等。求取出 n n 个巧克力后桌面上剩余 m m 个巧克力的概率。
数据范围
1 c 100 , 1 n , m 1000000 1\leq c\leq 100,1\leq n,m\leq 1000000

二、解法

发现最后还在桌面上的巧克力一定是出现奇数次的,我们把奇数和偶数的情况分别表示成母函数(0奇1偶),因为我们还需要考虑排列,相同颜色的排列必须要消去,所以我们把这个任务交给母函数的系数,最后在乘上 n ! n! 即可:
f 0 ( x ) = x 1 ! + x 3 3 ! + x 5 5 ! + . . . . . f_0(x)=\frac{x}{1!}+\frac{x^3}{3!}+\frac{x^5}{5!}+..... f 1 ( x ) = 1 0 ! + x 2 2 ! + x 4 4 ! + . . . . . f_1(x)=\frac{1}{0!}+\frac{x^2}{2!}+\frac{x^4}{4!}+..... 我们考虑用自然底数 e e 表示它们的闭形式,先给出一个结论, e x = ( 1 + 1 n ) n x = 1 + x 1 ! + x 2 2 ! + . . . . e^x=(1+\frac{1}{n})^{nx}=1+\frac{x}{1!}+\frac{x^2}{2!}+.... 下面给出证明:

结论一: e x e^x 等于 e x e^x 的求导

先证明等价无穷小,即 e x 1 = x e^x-1=x x x 趋近于 0 0 ),我们先设 y = e x 1 y=e^x-1 把两边取对数, x = ln ( y + 1 ) x=\ln(y+1) ,因为 x x 趋近于 0 0 ,所以 ln ( y + 1 ) \ln(y+1) 趋近于 1 1 ,推出 y y 趋近于 0 0 ,所以 e x 1 = x e^x-1=x

然后我们暴力对 e x e^x 求导:
e x + Δ x e x Δ x = e x ( e Δ x 1 ) Δ x = e x \frac{e^{x+\Delta x}-e^x}{\Delta x}=\frac{e^x\cdot(e^{\Delta x}-1)}{\Delta x}=e^x 运用了等价无穷小,问题得证。

结论二:泰勒展开很香

我们把 e x e^x x = 0 x=0 出泰勒展开,得到(注, f ( x ) = e x f(x)=e^x ):
f ( x ) = f ( x 0 ) + f ( x 0 ) 1 ! ( x x 0 ) + f ( x 0 ) 2 ! ( x x 0 ) 2 . . . . f(x)=f(x_0)+\frac{f'(x_0)}{1!}(x-x_0)+\frac{f''(x_0)}{2!}(x-x_0)^2.... f ( x ) = 1 + x 1 ! + x 2 2 ! + x 3 3 ! + . . . . . . f(x)=1+\frac{x}{1!}+\frac{x^2}{2!}+\frac{x^3}{3!}+...... 结合了结论一,故原等式成立。

然后我们可以把奇数和偶数的母函数用 e x e^x 表示出来:
f 0 ( x ) = e x e x 2 f_0(x)=\frac{e^x-e^{-x}}{2} f 1 ( x ) = e x + e x 2 f_1(x)=\frac{e^x+e^{-x}}{2} 所以我们要取出 m m 个颜色使它为奇数,取出 c m c-m 个颜色使它为偶数,把所有颜色整合后的母函数表示出来:
G ( x ) = C c m ( e x e x 2 ) m ( e x + e x 2 ) c m G(x)=C_c^m\cdot (\frac{e^x-e^{-x}}{2})^m\cdot(\frac{e^x+e^{-x}}{2})^{c-m} G ( x ) = 2 c C c m ( e x e x ) m ( e x + e x ) c m G(x)=2^{-c}\cdot C_c^m\cdot (e^x-e^{-x})^m\cdot (e^x+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 ( m c 2 j ) x G(x)=2^{-c}\cdot C_c^m\sum_{i=0}^m (-1)^i\cdot C_m^i\cdot e^{(m-2i)x}\sum_{j=0}^{c-m}C_{c-m}^j \cdot e^{(m-c-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}\cdot C_c^m\sum_{i=0}^m\sum_{j=0}^{c-m}(-1)^i\cdot C_m^i\cdot C_{c-m}^j\cdot e^{(c-2i-2j)x} 我们把上面的 e ( c 2 i 2 j ) x 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}\cdot C_c^m\sum_{i=0}^m\sum_{j=0}^{c-m}(-1)^i\cdot C_m^i\cdot C_{c-m}^j\cdot \sum_{k=0}^\infty \frac{((c-2i-2j)x)^k}{k!} 那么我们就可以暴力求第 n n 项的系数 a n a_n
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 ) x ) n n ! a_n=2^{-c}\cdot C_c^m\sum_{i=0}^m\sum_{j=0}^{c-m}(-1)^i\cdot C_m^i\cdot C_{c-m}^j\cdot \frac{((c-2i-2j)x)^n}{n!} 所以答案为:
a n n ! c n \frac{a_n\cdot n!}{c^n} 具体计算时,我们可以把答案的两个数乘到柿子的最后一项中,为了避免精度误差,我们最后在做除法,详见代码。

#include <cstdio>
#define db double
int read()
{
    int num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
    return num*flag;
}
int c,n,m;
db C[105][105];
db qkpow(db a,int b)
{
	db res=1;
	while(b>0)
	{
		if(b&1) res=res*a;
		a=a*a;
		b>>=1;
	}
	return res;
}
void init(int n)
{
	C[0][0]=1;
	for(int i=1;i<=n;i++)
	{
		C[i][0]=1;
		for(int j=1;j<=i;j++)
			C[i][j]=C[i-1][j-1]+C[i-1][j];
	}
}
signed main()
{
	init(100);
	while(scanf("%d",&c) && c)
	{
		n=read();m=read();
		if((n+m)%2 || m>n || m>c)
		{
			printf("0.000\n");
			continue;
		}
		db 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]*qkpow((c-2*i-2*j)*1.0/c,n);
		ans=ans*C[c][m]/qkpow(2,c);
		printf("%.3f\n",ans);
	}
}
发布了192 篇原创文章 · 获赞 12 · 访问量 3361

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/103718769