[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 } 
View Code

 

posted @ 2020-12-30 14:02  PYWBKTDA  阅读(108)  评论(0编辑  收藏  举报