zoukankan      html  css  js  c++  java
  • 洛谷 P4124 (数位 DP)

    ### 洛谷 P4124 题目链接 ###

     

    题目大意:

    给你一段区间,让你求满足下列两个条件时的数的个数。

    1、至少有 3 个相邻相同数字 (即 111 、1111 、222 等)

    2、不能同时出现 8 与 4 。

    给定的区段 [L,R] 中 ,L 与 R 的数值范围为:1010 ≤ L ≤ R  < 1011

    分析:
    1、用 q 与 w 标记 8 是否出现 ,4 是否出现。
    2、为了得知是否有连续三个相等,故还需要 ppre 表示前两位中的第一位数位上的数,pre 表示前一位数位上的数,还需要再加 flag 标记是否当前已满足 ppre == pre == i
    3、剩下的就是前导零与位数限制标记了 (即 lead 与 limit )

    故 dp 需要 5 维,pos、ppre、pre、flag、q、w ,然后直接记忆化即可。

    代码如下:

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    typedef long long ll;
    ll L,R;
    ll a[15];
    ll dp[15][15][15][2][2][2];
    ll dfs(int pos,int ppre,int pre,bool flag,bool q,bool w,bool lead,bool limit){
        if(pos==0) return flag&&(!(q&&w));
        if(!limit&&dp[pos][ppre][pre][flag][q][w]!=-1) return dp[pos][ppre][pre][flag][q][w];
        int up=limit?a[pos]:9;
        ll res=0;
        for(int i=0;i<=up;i++){
            if(lead&&i==0) res+=dfs(pos-1,-1,-1,false,false,false,true,limit&&i==a[pos]);
            else res+=dfs(pos-1,pre,i,(ppre==pre&&pre==i)||flag,(q||i==4),(w||i==8),false,limit&&i==a[pos]);
        }
        if(!limit) dp[pos][ppre][pre][flag][q][w]=res;
        return res;
    }
    ll solve(ll x)
    {
        int pos=0;
        while(x){
            a[++pos]=x%10;
            x/=10;
        }
        return dfs(pos,-1,-1,0,false,false,true,true);
    }
    int main()
    {
        //freopen("test.in","r",stdin);
        //freopen("test.out","w",stdout);
        memset(dp,-1,sizeof(dp));
        scanf("%lld%lld",&L,&R);
        printf("%lld
    ",solve(R)-solve(L-1) );
    }
  • 相关阅读:
    java poi 操作
    java map 根据 map的value值进行排序
    Windows navcat 连接虚拟机mysql
    如何阻止Windows广告窗口弹出
    python gitlab 学习笔记
    Java的家庭记账本程序(D)
    《程序员修炼之道:从小工到专家》的阅读笔记(二)
    Java的家庭记账本程序(C)
    Java的家庭记账本程序(B)
    Java的家庭记账本程序(A)
  • 原文地址:https://www.cnblogs.com/Absofuckinglutely/p/11430526.html
Copyright © 2011-2022 走看看