[hdu4652]Dice
(首先这道题有更为简单的dp+差分的做法,但以下为概率生成函数的做法)
第一问:
定义$f_{i}$表示(恰好)在第$i$个数结束的概率,$g_{i}$表示前$i$个数仍未结束的概率,则有$\frac{g_{i}}{m^{n-1}}=\sum_{j=1}^{n}\frac{f_{i+j}}{m^{n-j}}$,正确性考虑两边的意义——
左式是指前$i+n$个数满足前$i$个数中未结束且最后$n$个数相同的概率($m^{n-1}$是因为还有$m$种取值)
右式是对于上面这些$i+n$个数,选择其第一个结束的数$i+j$,则对于这一类$i+n$个数,相当于要求$f_{i+j}$以及$\frac{1}{m^{n-j}}$(对于后面$(i+j,i+n]$都要与之前的结尾相同)
(或许从方案数的角度更容易理解,即将$f_{i}$和$g_{i}$分别定义为所对应的方案数,对所有方案按照第一个结束的位置$i+j$分类,根据加法原理统计,由于独立性所以也可以将概率累加)
记$F(x)=\sum_{i=0}^{\infty}f_{i}x^{i}$、$G(x)=\sum_{i=0}^{\infty}g_{i}x^{i}$,将上述式子代入,即可得$G(x)=\sum_{i=1}^{n}m^{i-1}\frac{F(x)}{x^{i}}$
考虑答案即为$\sum_{i=1}^{\infty}(g_{i-1}-g_{i})i=\sum_{i=0}^{\infty}g_{i}=G(1)$,而$F(1)=\sum_{i=0}^{\infty}f_{i}=1$,因此将$x=1$代入该式即可得到$G(1)=\sum_{i=1}^{n}m^{i-1}=\frac{m^{n}-1}{m-1}$
第二问:
定义$f_{i}$表示(恰好)在第$i$个数结束的概率,$g_{i}$表示前$i$个数仍未结束的概率,同样考虑加入第$n$个数,即考虑对$P(前i+n个数满足前i个数中未结束且最后n个数不同)$的两种表示方法
第一种通过$g_{i}$表示即$\frac{A_{m}^{n}g_{i}}{m^{n}}$,对于这不同的$n$个数组合数显然是这样的
第二种枚举第一个合法的结尾$i+j$,即$\sum_{j=1}^{n}\frac{A_{m-j}^{n-j}f_{i+j}}{m^{n-j}}$(最后的$(i+j,i+n]$个数只需要与$(i,i+j]$不同就可以了,因此从$m-j$个中选$n-j$个)
记$F(x)=\sum_{i=0}^{\infty}f_{i}x^{i}$、$G(x)=\sum_{i=0}^{\infty}g_{i}x^{i}$,同样可得$G(x)=\sum_{i=1}^{n}\frac{(m-i)!m^{i}}{m!}\frac{F(x)}{x^{i}}$
答案为$G(1)=\sum_{i=1}^{n}\frac{(m-i)!m^{i}}{m!}$,直接计算即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 int t,p,m,n; 5 int main(){ 6 while (scanf("%d",&t)!=EOF){ 7 while (t--){ 8 scanf("%d%d%d",&p,&m,&n); 9 if (!p){ 10 ll ans=1; 11 for(int i=1;i<=n;i++)ans=ans*m; 12 printf("%.6f\n",1.0*(ans-1)/(m-1)); 13 } 14 else{ 15 double s=1,ans=0; 16 for(int i=1;i<=n;i++){ 17 s=s*m/(m-i+1); 18 ans+=s; 19 } 20 printf("%.6f\n",ans); 21 } 22 } 23 } 24 }