zoukankan      html  css  js  c++  java
  • hdu6829

    题意:

    有三个人各有x,y,z块钱,每次最多钱的人会把有1/2的概率給别人一块钱,问要给多少次,才能平均三个人的钱数。

    0<x,y,z<=1e6

    首先肯定是有明显的状态转移关系的。

    假设x>=y>z

    很容易列出dp[x][y][z]=1/2dp[x-1][y+1][z]+1/2dp[x-1][y][z+1]+1

    进一步很容易想到其实有一维可以优化掉,因为最小的那个肯定不会动,我只要知道最大的和中间的比它多多少就可以了。

    dp[x][y]=1/2dp[x-1][y+1]+1/2dp[x-2][y-1]+1 考虑xy分类讨论很麻烦想个简单点的

    设dp[x][y]表示较小的两个差最大的多少

    dp[x][y]=1/2dp[x-2][y-1]+1/2dp[x-1][y-2]+1;这个式子要求(x>=2,y>=2)

    然后看一眼复杂度,xyz的和是不大的。

    我们发现除了数轴的附近都是满足上面的式子的,所以说假如一个点(x,y)经过若干步走到(x1,y1)的概率是能算的,我们知道类型1走了多少次,类型2走了多少次,可以用组合数很快求出来,所以说我们处理数轴附近就好了。

    dp[x][1]=1/2dp[x-2][0]+1/2dp[x][1]+1   =>  dp[x][1]=dp[x-2][0]+2

    dp[x][0]=1/2dp[x-1][1]+1/2dp[x+1][2]+1 => dp[x][0]=1/2dp[x-1][1]+1/2(1/2dp[x][0]+1/2dp[x-1][1]+1)+1 => dp[x][0]=3/4dp[x-1][1]+1/4dp[x][0]+3/2 =>dp[x][0]=dp[x-1][1]+2

    我们发现0和1的数字只设计到了内部的0和1,所以是可以dp求的。

    所以数轴附近的就可以做了。

    写完之后的体会,感觉还是很难写的,虽然说你把一个点跑到其他点的概率都全了,但是你会发现数轴上那个高度为1的点还是能走到高度为0的点,直接算会导致重复,所以说要算到达高度0的点事,要避开高度为1的点,简单的想法就是取上一个点的概率的一半就行了,(因为到达一个点只有两个前驱,不是那个就是另外一个,而且有1/2的概率通往其他点)

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #define R int
    #define I inline void
    #define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin))
    #define lc c[x][0]
    #define rc c[x][1]
    typedef long long ll;
    using namespace std;
    const int maxn=1e6+20;
    const int mod=998244353;
    ll quick(ll a,ll b,ll m)
    {
        ll ans=1;
        while(b>0)
        {
            if(b&1)
                ans=ans*a%m;
            a=a*a%m;
            b>>=1;
        }
        return ans;
    }
    ll jiecheng[maxn];
    void ini_zuhelogn()
    {
        jiecheng[0]=1;
        for(int i=1;i<maxn;i++)
        {
            jiecheng[i]=jiecheng[i-1]*i%mod;
        }
    }
    ll zuhe_logn(int m,int n)
    {
        if(jiecheng[0]!=1)
            ini_zuhelogn();
        ll ans=((jiecheng[m]*quick(jiecheng[n], mod-2, mod))%mod)*quick(jiecheng[m-n], mod-2, mod)%mod;
        return ans;
    }
    
    int dp[maxn][2];
    int main()
    {
        dp[0][0]=0;
        for(int i=3;i<1e6;i+=3)
        {
            dp[i-1][1]=dp[i-3][0]+2;
            dp[i][0]=dp[i-1][1]+2;
        }
        int T=0;
        ll inv_2=quick(2, mod-2, mod);
        scanf("%d",&T);
        while (T--) {
            int x[3];
            scanf("%d%d%d",&x[0],&x[1],&x[2]);
            if((x[0]+x[1]+x[2])%3!=0)
            {
                printf("-1
    ");
                continue;
            }
            sort(x, x+3);
            int x1=x[2]-x[0],y1=x[2]-x[1];
            ll ans=0;
            
            
            for(int i=3;i<=x1;i+=3)
            {
                //(i-1 1) (i ,0)
                //(x1,y1)
                int x2=x1-(i-1),y2=y1-1;
                
                int xuyao=(2*x2-y2)/3,xuyao_bu=(2*y2-x2)/3;
                if(xuyao<0||xuyao_bu<0)
                {
                    
                }
                else
                {
                    //cout<<(dp[i-1][1]+(x2+y2)/3)<<endl<<zuhe_logn((x2+y2)/3, xuyao)<<endl<<quick(inv_2, (x2+y2)/3, mod)<<endl;
                    ans=(ans+((dp[i-1][1]+(x2+y2)/3)*zuhe_logn((x2+y2)/3, xuyao)%mod)*quick(inv_2, (x2+y2)/3, mod))%mod;
                }
                
                x2=x1-(i+1);y2=y1-2;
                xuyao=(2*x2-y2)/3;xuyao_bu=(2*y2-x2)/3;
                if(xuyao<0||xuyao_bu<0)
                {
                    
                }
                else
                {
                    //cout<<(dp[i][0]+(x2+y2)/3+1)<<endl<<zuhe_logn((x2+y2)/3, xuyao)<<endl<<quick(inv_2, (x2+y2)/3+1, mod)<<endl;
                    
                    ans=(ans+((dp[i][0]+(x2+y2)/3+1)*zuhe_logn((x2+y2)/3, xuyao)%mod)*quick(inv_2, (x2+y2)/3+1, mod))%mod;
                }
            }
            
            for(int i=3;i<=y1;i+=3)
            {
                //(1 i-1) (0 ,i)
                //(x1,y1)
                
                int x2=x1-1,y2=y1-(i-1);
                
                int xuyao=(2*x2-y2)/3,xuyao_bu=(2*y2-x2)/3;
                if(xuyao<0||xuyao_bu<0)
                {
                    
                }
                else
                {
                    //cout<<(dp[i-1][1]+(x2+y2)/3)<<endl<<zuhe_logn((x2+y2)/3, xuyao)<<endl<<quick(inv_2, (x2+y2)/3, mod)<<endl;
                    ans=(ans+((dp[i-1][1]+(x2+y2)/3)*zuhe_logn((x2+y2)/3, xuyao)%mod)*quick(inv_2, (x2+y2)/3, mod))%mod;
                }
                
                
                x2=x1-2;y2=y1-(i+1);
                
                xuyao=(2*x2-y2)/3;xuyao_bu=(2*y2-x2)/3;
                if(xuyao<0||xuyao_bu<0)
                {
                    
                }
                else
                {
                    //cout<<(dp[i][0]+(x2+y2)/3+1)<<endl<<zuhe_logn((x2+y2)/3, xuyao)<<endl<<quick(inv_2, (x2+y2)/3+1, mod)<<endl;
                    ans=(ans+((dp[i][0]+(x2+y2)/3+1)*zuhe_logn((x2+y2)/3, xuyao)%mod)*quick(inv_2, (x2+y2)/3+1, mod))%mod;
                }
                
            }
            
            if(x1==0||x1==1||y1==0||y1==1)
                ans=dp[x1][y1];
            
            printf("%lld
    ",ans);
            
        }
        
    }
    //748683271
  • 相关阅读:
    32、至少列举8个常用模块都有那些?
    31、如何安装第三方模块?以及用过哪些第三方模块?
    uva120 Stacks of Flapjacks (构造法)
    stringstream的基本用法
    Codeforces Round #246 (Div. 2) C. Prime Swaps(贪心,数论)
    Codeforces Round #271 (Div. 2)D(递推,前缀和)
    poj3061 Subsequence&&poj3320 Jessica's Reading Problem(尺取法)
    Codeforces Round #266 (Div. 2)B(暴力枚举)
    uva10815(set的应用)
    uva489(需要考虑周全)
  • 原文地址:https://www.cnblogs.com/King-of-Dark/p/13495054.html
Copyright © 2011-2022 走看看