zoukankan      html  css  js  c++  java
  • Luogu_3239 [HNOI2015]亚瑟王

    Luogu_3239 [HNOI2015]亚瑟王

    vim-markdown 真好用
    这个题难了我一下午

    第一道概率正而八经(DP),还是通过qbxt讲解才会做的。

    发现Sengxian真是个dalao。讲的真是很清楚。代码也比较干净

    做题心得:
    1.概率和期望联系紧密。若无法直接计算期望,可是用期望的性质,将问题转化为算概率
    2.若目标概率无法直接计算,可以通过计算过程中的某个步骤的概率,间接的计算出目标概率

    若跟据局面进行状压(DP),时间复杂度成熟不起。

    考虑优化状态。

    发现,对于某一张牌,我们只要知道他用没有用过就行了。

    所以一个很重要的操作就是定序。

    我们只需要枚举某一张牌。在某一个局面中是否会被选中就可以了。

    根据某一个局面出现的概率,便可计算出某一张牌在某个局面被选的概率,从而推出期望。

    那么问题就是推出这个局面出现的概率。也就是过程中某个步骤的概率。

    我们可以更改一下决策, 我们只需要枚举在某一个局面中。要么在剩余j轮(也就是当前局面)的时候被选中,要么在永远不会被选中

    然后直接转移到决策下一张卡。

    这样做, 我们可以避免同一张卡之间不同决策之间的互相影响, 又可以不丢失任何答案。


    (f_{i,j})为前(i)张卡牌已经决策完了,还剩下(j)局可以进行

    根据上面的说明,便可以写出状态转移方程

    (f_{i,j}=f_{i-1,j}*(1-p_i)^j+f_{i-1,j+1}*(1-(1-p_i)^{j+1}))

    
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <bitset>
    
    using std::bitset;
    
    const int maxn=101000;
    const int MAX=100000;
    const long long mod=1000000001;
    const int log_2=17;
    const int log_3=11;
    
    int n;
    long long map[log_2][300];
    int check[log_2][log_3];
    int Log_2,Log_3;
    int len[log_2];
    int step[maxn],tot;
    bitset<maxn>vis;
    
    void init()
    {
        for(int i=0;i<(1<<log_3);i++)
            if((i&(i<<1))==0) 
                step[++tot]=i;
        return ;
    }
    
    double Log(int base,int val)
    {
        return log(val)/log(base);
    }
    
    long long calc(int limte)
    {   
        memset(map,0,sizeof(map));
        memset(check,0,sizeof(check));
        memset(len,0,sizeof(len));
        int wide=0;
        for(int &i=wide,pas1=limte;i<=Log_2&&pas1<=n;i++,pas1<<=1)
            for(int j=0,pas2=pas1;j<=Log_3&&pas2<=n;j++,pas2*=3)
            {
                check[i][j]=pas2,len[i]|=(1<<j);
                vis[pas2]=1;
            }
        wide-=1;
        for(int i=1;step[i]<=len[0]&&i<=tot;i++)
            map[0][i]=1;
        for(int i=0;i<wide;i++)
            for(int j=1;step[j]<=len[i]&&j<=tot;j++) 
                for(int k=1;step[k]<=len[i+1]&&k<=tot;k++)
                    if((step[j]&step[k])==0)  
                        map[i+1][k]=(map[i][j]+map[i+1][k])%mod;
        long long ans=0;
        for(int i=0;step[i]<=len[wide];i++)
            ans=(ans+map[wide][i])%mod;
        return ans;
    }
    
    int main()
    {
        init();
        scanf("%d",&n);
        Log_2=Log(2,n);Log_3=Log(3,n);
        long long ans=1;
        for(int i=1;i<=n;i++)
            if(!vis[i])
                ans=(ans*calc(i))%mod;
        printf("%lld",ans);
    }
    
  • 相关阅读:
    TreeView控件
    俄罗斯套娃
    c#文件操作
    c# 操作excle
    vs2010启动越来越慢解决方法
    c# 操作excle[转]
    c# 命名空间别名
    C# openfiledialog的使用
    c# 获取项目根目录方法
    jquery操作复选框(checkbox)的12个小技巧总结
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/10385837.html
Copyright © 2011-2022 走看看