zoukankan      html  css  js  c++  java
  • 【BZOJ4521】[CQOI2016] *(数位DP)

    点此看题面

    大致题意: 问有多少个(Lsim R)的整数,满足至少有(3)个相邻的相同数字,且不能同时出现(4)(8)

    数位(DP)

    好久没写过数位(DP)了,结果不出所料写出一个无比智障的错误(枚举数码的时候居然写了一个小于(9)。。。)

    感觉我的(DP)可能有些复杂,考虑设(f_{x,k,g,t})表示当前枚举到第(x)位,(k=0/1/2)分别表示没有出现(4)(8)出现了(4)出现了(8)(g)表示当前正在连续的数字,(t)表示连续的数字有几个。

    特殊地,令(g=10,t=0)表示已经存在(3)个相邻的相同数字。

    则枚举时只要单独处理(4)(8)的情况即可。

    由于位数是相同的,存在前导(0)的情况会被相互抵消掉,因此懒了点没有判前导(0)

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 2000
    #define LL long long
    using namespace std;
    int l,v[20];LL n,m,S[20][3][15][4];
    I LL DP(CI x,CI k=0,RI g=-1,RI t=0,CI f=0)//数位DP,f表示是否严格小于
    {
    	if(t==3&&(g=10,t=0),f&&~S[x][k][g][t]) return S[x][k][g][t];if(!x) return g==10;LL res=0;//用g=10,t=0表示符合条件,边界直接返回
    	k^2&&(f||v[x]>=4)&&(res+=DP(x-1,1,g^10?4:10,g^10?(g^4?1:t+1):0,f||v[x]>4));//单独处理4
    	k^1&&(f||v[x]>=8)&&(res+=DP(x-1,2,g^10?8:10,g^10?(g^8?1:t+1):0,f||v[x]>8));//单独处理8
    	for(RI i=0;i<=9;++i) i^4&&i^8&&(f||v[x]>=i)&&(res+=DP(x-1,k,g^10?i:10,g^10?(g^i?1:t+1):0,f||v[x]>i));//枚举其余数码
    	return f&&(S[x][k][g][t]=res),res;//记忆化
    }
    I LL Get(LL x) {l=0;W(x) v[++l]=x%10,x/=10;v[l+1]=0;return memset(S,-1,sizeof(S)),DP(11);}//分到数组中然后DP
    int main() {return scanf("%lld%lld",&n,&m),printf("%lld
    ",Get(m)-Get(n-1)),0;}//差分
    
  • 相关阅读:
    ubuntu配置服务器环境
    discuz安装与学习资料
    前端面试题总结(一)
    css公共样式,初始化
    js的解析--预处理(三)
    sass的安装与基础
    移动开发学习笔记(一) 移动开发的注意事项
    移动前端一些常用的框架
    JavaScript的构造器与对象(二)
    JavaScript 中的Object的使用详解笔记(一)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4521.html
Copyright © 2011-2022 走看看