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;}//差分
    
  • 相关阅读:
    windows10使用记录
    DevOps理论与实践总结
    工资调整
    Node程序debug小记
    基于游标的分页接口实现
    util.promisify 的那些事儿
    如何编写 Typescript 声明文件
    async语法升级踩坑小记
    使用TS+Sequelize实现更简洁的CRUD
    使用 TypeScript 改造构建工具及测试用例
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4521.html
Copyright © 2011-2022 走看看