zoukankan      html  css  js  c++  java
  • [loj6118]鬼牌

    枚举最终所有牌的大小$i$,对于最终所有牌大小都为$i$的情况,令其贡献为步数,否则令其贡献为0,记$F$为期望贡献(即所有情况概率*贡献之和),答案即为$sum_{i=1}^{m}F$

    显然,$F$仅取决于牌的数量,定义$F_{i}$表示恰有$i$张牌的期望贡献,那么答案即为$sum_{i=1}^{m}F_{a_{i}}$

    在求$F_{i}$的转移之前,先定义$P_{i}$为贡献为步数的情况的概率,关于$P_{i}$的转移,不难得到
    $$
    egin{cases}P_{0}=0,P_{n}=1\P_{i}=frac{P_{i-1}+P_{i+1}}{2}&(1le i<n)end{cases}
    $$
    这是一个经典的问题,通项为$P_{i}=frac{i}{n}$

    考虑$F_{i}$的转移,即为
    $$
    egin{cases}F_{0}=F_{n}=0\F_{i}=frac{i(n-i)}{n(n-1)}(F_{i-1}+F_{i+1}+frac{2i}{n})+(1-frac{2i(n-i)}{n(n-1)})(F_{i}+frac{i}{n})&(1le i<n)end{cases}
    $$
    (注意每一次步数并不是+1,而是加上目标状态的$P_{i}$,因为只有$P_{i}$的概率这步有贡献)

    将其化简,即为
    $$
    egin{cases}F_{0}=F_{n}=0\F_{i+1}=2F_{i}-F_{i-1}-frac{n-1}{n-i}&(1le i<n)end{cases}
    $$
    将其差分,即令$G_{i}=F_{i+1}-F_{i}$,那么
    $$
    egin{cases}G_{0}=F_{1},sum_{i=0}^{n-1}G_{i}=0\G_{i}=G_{i-1}-frac{n-1}{n-i}&(1le i<n)end{cases}
    $$
    将第2个式子不断迭代,即可得$G_{i}=F_{1}-sum_{j=1}^{i}frac{n-1}{n-j}$,那么
    $$
    sum_{i=0}^{n-1}G_{i}=nF_{1}-sum_{i=0}^{n-1}sum_{j=1}^{i}frac{n-1}{n-j}=nF_{1}-sum_{j=1}^{n-1}frac{n-1}{n-j}(n-j)=nF_{1}-(n-1)^{2}=0
    $$
    解得$F_{1}=frac{(n-1)^{2}}{n}$,进而可得
    $$
    F_{i}=sum_{j=0}^{i-1}G_{j}=iF_{1}-sum_{j=1}^{i-1}frac{n-1}{n-j}(i-j)=frac{i(n-1)^{2}}{n}-(i-1)(n-1)+(n-i)(n-1)sum_{j=n-i+1}^{n-1}frac{1}{j}
    $$
    (最后一个变化是将$i-j$变形为$(n-j)-(n-i)$,再根据分配律展开即可)

    关于最后一项,令$H_{n}=sum_{i=1}^{n}frac{1}{i}$,即$H_{n}-H_{n-i}$,关于$H_{n}$为调和级数,用$H_{n}=ln n+C$来模拟即可(较小范围预处理,$C$使用0.5772即可,当然还可以分块打表)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 10000005
     4 #define C 0.5772
     5 #define ld long double
     6 int n,m,x;
     7 ld nn,ans,h[N];
     8 ld H(int n){
     9     if (n<N)return h[n];
    10     return log(n)+C;
    11 }
    12 ld calc(int k){
    13     return k*(nn-1)*(nn-1)/nn-(k-1)*(nn-1)+(nn-k)*(nn-1)*(H(n-1)-H(n-k));
    14 }
    15 int main(){
    16     for(int i=1;i<N;i++)h[i]=h[i-1]+(ld)1/i;
    17     scanf("%d%d",&n,&m);
    18     nn=n;
    19     for(int i=1;i<=m;i++){
    20         scanf("%d",&x);
    21         ans+=calc(x);
    22     }
    23     printf("%.7Lf",ans);
    24 }
    View Code
  • 相关阅读:
    【本人译作推荐】Windows 8应用开发:C#和XAML卷(原名:Building Windows 8 Apps with C# and XAML)
    ODAC的安装以及Entity Framework for Oracle 基本配置
    ExtJs API 下载以及部署
    ArcGis(01)——地图切片以及发布底图服务
    ubuntu下安装Vmare Workstation,并安装mac补丁
    sencha app build 到 Capturing theme image不执行
    Ext Sencha Cmd 6 环境安装
    SqlServer CTE 递归查询 Oracle递归查询
    ibatis.net调用oracle存储过返回游标SYS_REFCURSOR结果集
    SpringMVC从入门到精通之第四章
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15010970.html
Copyright © 2011-2022 走看看