Chocolate(母函数)(POJ-1322)

文章目录

题目

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

思路

我们首先考虑数据的合法性:
a. n , m 同 奇 偶 n,m同奇偶 n,m
b. m &lt; = n a n d m &lt; = c m&lt;=n\quad and \quad m&lt;=c m<=nandm<=c
那么我们可以发现 n − m n-m nm 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(2exex)m(2ex+ex)cm
解释一下,这表示我们首先确定取奇数的方案数 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)=2cCcm(exex)m(ex+ex)cm
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)=2cCcmi=0m(1)iCmie(m2i)xj=0cmCcmje(cm2j)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)=2cCcmi=0mj=0cm(1)iCmiCcmje(c2i2j)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)=2cCcmi=0mj=0cm(1)iCmiCcmjk=0+k!((c2i2j)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=2cCcmi=0mj=0cm(1)iCmiCcmjn!(c2i2j)n
所以符合条件的方案数为 a n ∗ n ! a_n*n! ann! ,我们发现总方案数为: c n c^n cn
所以概率为:
a n ∗ n ! c n \frac{a_n*n!}{c^n} cnann!
注意,尽量将除法放在最后减小精度误差

代码

#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;
}
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值