zoukankan      html  css  js  c++  java
  • 数位DP小小结

    FZOJ Problem 2113 Jason的特殊爱好

    题意:x~y数字里面有多少个 1 

    思路:我们算法课实验题的简化版,当时我用了很麻烦的一个DP=_=

    刚刚学到了很棒的姿势,记忆化DP!!

    dfs(int pos ,bool end1) ;

    end1==false 返回pos位后面(包含pos)任意组合有多少个 1 ;

    end1==true 返回上一位是结尾,Pos以后的位受到限制组合有多少个 1 ;

    大概是这样,如果数字是 4987 现在计算到 8 这个数字,end1==true,说明是49XX

    XX的取值是0-87;

    如果计算到当前位,如果是这位是1 ,如果没有限制,那么答案就是加上10^pos个

    如果有限制,那么答案就是加上nn%(10^pos)+1 个,

    如果不是结尾(也就是没有限制的),我们可以dp[pos]保存计算过的结果。

    include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<set>
    #include<stack>
    #include<map>
    #include<ctime>
    #include<bitset>
    #define LL long long
    #define ll long long
    #define INF 0x3f3f3f3f
    #define maxn 50010
    #define eps 1e-6
    #define mod 1000000007
    using namespace std;
    
    LL dp[30] ,nn ;
    int bit[30] ;
    
    LL get1(int pos)
    {
        LL tt=1;
        for(int i=0;i<pos;i++)
            tt *= 10;
        return nn%tt;
    }
    LL get2(int pos)
    {
        LL tt=1;
        for(int i=0;i<pos;i++)
            tt *= 10;
        return tt;
    }
    LL dfs(int pos ,bool end1)
    {
        if(pos==-1)
        {
            return 0;
        }
        if(!end1&&dp[pos] != -1)
        {
            return dp[pos];
        }
        int e ,ee ;
        LL ans=0;
        if(end1) e = bit[pos] ;
        else e = 9 ;
        for(int i = 0 ; i <= e ;i++)
        {
            if(i==1){
                 if(i==e)ans += get1(pos)+1;
                 else ans += get2(pos) ;
            }
            ans += dfs(pos-1,(end1&&i==e)) ;
        }
        if(!end1)
        {
            dp[pos] = ans;
        }
        return ans;
    }
    LL getans(LL n )
    {
        nn=n;
        int len=0;
        if(n<=0) return 0 ;
        while(n)
        {
            bit[len++] = n%10 ;
            n /= 10 ;
        }
        LL ans=0;
        ans = dfs(len-1,1) ;
        return ans;
    }
    int main()
    {
        int i , j , m ,k ,T ;
        LL x,y ;
        memset(dp,-1,sizeof(dp)) ;
       // cout << getans(20)<<endl;
        while(cin >> x >> y)
        {
            y=getans(y) ;
            x=getans(x-1);
            cout << y-x<< endl;
        }
        return 0 ;
    }
    View Code

    hdu 3555 Bomb

    题意:x~y数字里面有多少个49 

    思路:和上面做法差不多,只是多了一个状态

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<set>
    #include<stack>
    #include<map>
    #include<ctime>
    #include<bitset>
    #define LL long long
    #define ll long long
    #define INF 0x3f3f3f3f
    #define maxn 50010
    #define eps 1e-6
    #define mod 1000000007
    using namespace std;
    
    LL dp[30][20] ,nn ;
    int bit[30] ;
    
    LL dfs(int pos ,int num ,bool end1)
    {
        if(pos==-1)
        {
            return num==2 ;
        }
        if(!end1&&dp[pos][num] != -1)
        {
            return dp[pos][num];
        }
        int e,ee;
        LL ans=0;
        if(end1) e = bit[pos] ;
        else e = 9 ;
        for(int i = 0 ; i <= e ;i++)
        {
            if(num==1&&i==9)
            {
                ee=2;
            }
            else if(num==0&&i==4)
            {
                ee=1;
            }
            else if(num==1&&i != 4)
            {
                ee=0;
            }
            else ee=num ;
            ans += dfs(pos-1,ee,(end1&&i==e)) ;
        }
        if(!end1)
        {
            dp[pos][num] = ans;
        }
        return ans;
    }
    LL getans(LL n )
    {
        nn=n;
        int len=0;
        if(n<=0) return 0 ;
        while(n)
        {
            bit[len++] = n%10 ;
            n /= 10 ;
        }
        LL ans=0;
        ans = dfs(len-1,0,1) ;
        return ans;
    }
    int main()
    {
        int i , j , m ,k ,T ;
        LL x,y ;
        memset(dp,-1,sizeof(dp)) ;
       // cout << getans(20)<<endl;
        cin >> T ;
        while(cin >> y)
        {
            y=getans(y) ;
            cout << y<< endl;
        }
        return 0 ;
    }
    View Code

    hdu 3709 Balanced Number

    题意:x-y有多少个是平衡的,平衡的定义是,找一个支点,使得两边的重量一样

    思路:  还是和上面的姿势一样,只是状态多了一些~~~

    对于  dfs(int pos ,int v,int val,bool end1)

    if(end1==false)表示当前计算到第pos位,选的支点为v,前面比后面的重val,后面pos位任意组合

    返回的数字数目。

    if(end1==true)也就是有限制了

    include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<set>
    #include<stack>
    #include<map>
    #include<ctime>
    #include<bitset>
    #define LL long long
    #define ll long long
    #define INF 0x3f3f3f3f
    #define maxn 50010
    #define eps 1e-6
    #define mod 1000000007
    using namespace std;
    
    LL dp[20][20][2000] ;
    int bit[30] ;
    
    LL dfs(int pos ,int v,int val,bool end1)
    {
        if(pos==-1)
        {
            return (val==0) ;
        }
        if(!end1&&dp[pos][v][val] != -1)
        {
            return dp[pos][v][val] ;
        }
        if(val<0) return 0 ;
        int e ,ee ;
        LL ans=0;
        if(end1) e = bit[pos] ;
        else e = 9 ;
        for(int i = 0 ; i <= e ;i++)
        {
            ee = val+(pos-v)*i ;
            ans += dfs(pos-1,v,ee,(end1&&i==e)) ;
        }
        if(!end1)
        {
            dp[pos][v][val] = ans;
        }
        return ans;
    }
    LL getans(LL n )
    {
        int len=0;
        if(n<0) return 0 ;
        while(n)
        {
            bit[len++] = n%10 ;
            n /= 10 ;
        }
        LL ans=0;
        for( int i = 0 ; i <len ;i++)
        {
            ans += dfs(len-1,i,0,1) ;
        }
        return ans-(len-1) ;
    }
    int main()
    {
        int i , j , m ,k ,T ;
        LL x,y ;
        memset(dp,-1,sizeof(dp)) ;
        cin >> T ;
        while(T--)
        {
            cin >> x >> y ;
            y=getans(y) ;
            x=getans(x-1);
            cout << y-x<< endl;
        }
        return 0 ;
    }
    View Code
  • 相关阅读:
    OS-lab4
    OS-lab3
    OS-lab2
    OS-lab1
    OO第四单元总结
    OO第三单元总结
    OO第二单元总结
    HTTP_POST
    实习日志1(2020.7.27-2020.9.31)
    Web app ------ 从Servlet读取Json数据并显示,生成历史数据曲线图
  • 原文地址:https://www.cnblogs.com/20120125llcai/p/4066259.html
Copyright © 2011-2022 走看看