zoukankan      html  css  js  c++  java
  • HDU 4588 Count The Carries 数位DP || 打表找规律

    2013年南京邀请赛的铜牌题。。。做的非常是伤心。另外有两个不太好想到的地方。。

    。。a 能够等于零,另外a到b的累加和比較大。大约在2^70左右。


    首先说一下解题思路。

    首先统计出每一位的1的个数,然后统一进位。

    设最低位为1。次低位为2,依次类推,ans[]表示这一位上有多少个1。那么有

    sum += ans[i]/2,ans[i+1] += ans[i]/2;

    sum即为答案。

    好了,如今问题转化成怎么求ans[]了。


    打表查规律比較奇妙,上图不说话。


    打表的代码

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <map>
    
    #pragma comment(linker, "/STACK:1024000000");
    #define EPS (1e-8)
    #define LL long long
    #define ULL unsigned long long
    #define _LL __int64
    #define _INF 0x3f3f3f3f
    #define Mod 9999991
    #define lowbit(x) (x&(-x))
    
    using namespace std;
    
    void out(int x)
    {
        while(x)
        {
            printf("%d",x&1);
            x >>= 1;
        }
    }
    
    int main()
    {
        for(int i = 1;i <= 100; ++i)
        {
            printf("i = %3d : ",i);
            out(i);
            puts("");
        }
    
        return 0;
    }
    


    好了。重头戏来了。这个数位DP做的还是非常有成就感的。

    记忆化搜索 + bfs推送

    昨天事实上想这个思路了。

    只是当时比較着急没写出来,心态是个非常重要的东西。

    记忆化搜索部分dp[sta][site][dig] 第一维表示是否到达上限,site表示第几位,dig表示是1还是0。

    那么site == 1时,也就是说最高位记录的信息是正确的。可是其它的就不是想要的了。

    由于dp[sta][site][sta] 表示当前位到最低位的方案数。

    所以说要把最高位的答案推送下去。

    推送非常easy,每种状态最多仅仅会由两种子状态得到,所以按比例推送一下即可了。

    详见代码。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <map>
    
    #pragma comment(linker, "/STACK:1024000000");
    #define EPS (1e-8)
    #define LL long long
    #define ULL unsigned long long
    #define _LL __int64
    #define _INF 0x3f3f3f3f
    #define Mod 9999991
    #define lowbit(x) (x&(-x))
    
    using namespace std;
    
    _LL dp[2][105][2],dp1[2][105][2];
    
    _LL up[105];
    
    _LL ansa[105],ansb[105];
    
    _LL dfs(_LL sta,_LL site,_LL dig)
    {
        if(dp[sta][site][dig] != -1)
            return dp[sta][site][dig];
        if(site == 100)
        {
            dp[sta][site][dig] = 1;
            return 1;
        }
    
        dp[sta][site][dig] = 0;
    
        if(sta == 0)
        {
            dp[sta][site][dig] = dfs(0,site+1,0) + dfs(0,site+1,1);
        }
        else
        {
            if(up[site+1] == 1)
            {
                dp[sta][site][dig] = dfs(1,site+1,1) + dfs(0,site+1,0);
            }
            else
            {
                dp[sta][site][dig] = dfs(1,site+1,0);
            }
        }
        return dp[sta][site][dig];
    }
    
    void Cal(_LL x,_LL *ans)
    {
        _LL temp = x,len = 100;
    
        memset(ans,0,sizeof(_LL)*(102));
    
        if(x == 0)
            return ;
        while(temp)
        {
            up[len--] = temp%2;
            temp /= 2;
        }
    
        len++;
        memset(dp,-1,sizeof(dp));
        dfs(1,len,1);
        dfs(0,len,0);
        _LL i;
    
        memset(dp1,0,sizeof(dp1));
    
        dp1[1][len][1] = max((_LL)0,dp[1][len][1]);
        dp1[1][len][0] = max((_LL)0,dp[1][len][0]);
        dp1[0][len][1] = max((_LL)0,dp[0][len][1]);
        dp1[0][len][0] = max((_LL)0,dp[0][len][0]);
    
        for(_LL site = len;site <= 99; ++site)
        {
            dp1[0][site+1][1] += dp1[0][site][1]*dp[0][site+1][1]/(dp[0][site+1][1] + dp[0][site+1][0]);
            dp1[0][site+1][1] += dp1[0][site][0]*dp[0][site+1][1]/(dp[0][site+1][1] + dp[0][site+1][0]);
            dp1[0][site+1][0] += dp1[0][site][1]*dp[0][site+1][0]/(dp[0][site+1][1] + dp[0][site+1][0]);
            dp1[0][site+1][0] += dp1[0][site][0]*dp[0][site+1][0]/(dp[0][site+1][1] + dp[0][site+1][0]);
    
            if(up[site+1] == 1)
            {
                if(up[site] == 1)
                {
                    dp1[1][site+1][1] += dp1[1][site][1]*dp[1][site+1][1]/(dp[1][site+1][1] + dp[0][site+1][0]);
                    dp1[0][site+1][0] += dp1[1][site][1]*dp[0][site+1][0]/(dp[1][site+1][1] + dp[0][site+1][0]);
                }
                else
                {
                    dp1[1][site+1][1] += dp1[1][site][0]*dp[1][site+1][1]/(dp[1][site+1][1] + dp[0][site+1][0]);
                    dp1[0][site+1][0] += dp1[1][site][0]*dp[0][site+1][0]/(dp[1][site+1][1] + dp[0][site+1][0]);
                }
            }
            else
            {
                dp1[1][site+1][0] = dp1[1][site][0] + dp1[1][site][1];
            }
        }
    
        for(i = len;i <= 100; ++i)
        {
            ans[i] = max((_LL)0,dp1[1][i][1]) + max((_LL)0,dp1[0][i][1]);
        }
    }
    
    int main()
    {
        _LL a,b,i;
    
        while(scanf("%I64d %I64d",&a,&b) != EOF)
        {
            Cal(b,ansb);
            Cal(max((_LL)0,a-1),ansa);
    
            _LL sum = 0;
    
            for(i = 100;i >= 1; --i)
            {
                sum += (ansb[i]-ansa[i])/2;
                ansb[i-1] += (ansb[i]-ansa[i])/2;
            }
            printf("%I64d
    ",sum);
        }
    
        return 0;
    }



  • 相关阅读:
    7、cad图纸打印
    对账
    练习10—去掉图片文字
    6、cad里面如何快速将图纸的线条全部变成黑色
    5、cad如何快速选中图纸上所有文字
    4、如何修改cad的背景色为白色
    练习九—快速修饰面部光影
    iOS alloc&init探索
    export default / export const
    Vue2.0+组件库总结
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7044010.html
Copyright © 2011-2022 走看看