CQOI2016 Number - 数位dp
2016-04-10 19:36
162 查看
分析:
dp[哪一位][前一个数的倒数第二位][前一个数的倒数最后一位][0/1表示是否满足了至少有三个相邻数字的要求][0/1/2 (0:没有8和4;1:有8;2:有4)][0/1表示最高位到当前位小于或者等于R]具体转移都在代码里了。
#include<cstdio> #include<cstring> #define MAXL 20 typedef long long LL; int lmt[MAXL+10]; LL dp[MAXL+10][20][20][5][5][5]; int Getorg(LL num){ int ret=0; for(LL x=num;x;x/=10) ret++; memset(lmt,0,sizeof lmt); int k=0; for(LL x=num;x;x/=10,k++) lmt[ret-k]=x%10; return ret; } inline int f(int x){ if(x==8) return 1; else if(x==4) return 2; else return 0; } inline int h(int x,int y,int z){ if(x==y&&y==z) return 1; else return 0; } LL DP(LL R) { int n=Getorg(R); if(R==10000000000LL-1) return 0; memset(dp,0,sizeof dp); for(int i=1;i<lmt[1];i++) dp[1][0][i][0][f(i)][0]=1; dp[1][0][lmt[1]][0][f(lmt[1])][1]=1; for(int i=2;i<=n;i++){ for(int j=0;j<=9;j++) for(int k=0;k<=9;k++){ // < R for(int p=0;p<=9;p++) dp[i][k][p][h(j,k,p)][f(p)][0]+=dp[i-1][j][k][0][0][0]; for(int p=0;p<=9;p++){ if(p==4) continue; dp[i][k][p][h(j,k,p)][1][0]+=dp[i-1][j][k][0][1][0]; } for(int p=0;p<=9;p++){ if(p==8) continue; dp[i][k][p][h(j,k,p)][2][0]+=dp[i-1][j][k][0][2][0]; } for(int p=0;p<=9;p++) dp[i][k][p][1][f(p)][0]+=dp[i-1][j][k][1][0][0]; for(int p=0;p<=9;p++){ if(p==4) continue; dp[i][k][p][1][1][0]+=dp[i-1][j][k][1][1][0]; } for(int p=0;p<=9;p++){ if(p==8) continue; dp[i][k][p][1][2][0]+=dp[i-1][j][k][1][2][0]; } // < R for(int p=0;p<lmt[i];p++) dp[i][k][p][h(j,k,p)][f(p)][0]+=dp[i-1][j][k][0][0][1]; for(int p=0;p<lmt[i];p++){ if(p==4) continue; dp[i][k][p][h(j,k,p)][1][0]+=dp[i-1][j][k][0][1][1]; } for(int p=0;p<lmt[i];p++){ if(p==8) continue; dp[i][k][p][h(j,k,p)][2][0]+=dp[i-1][j][k][0][2][1]; } for(int p=0;p<lmt[i];p++) dp[i][k][p][1][f(p)][0]+=dp[i-1][j][k][1][0][1]; for(int p=0;p<lmt[i];p++){ if(p==4) continue; dp[i][k][p][1][1][0]+=dp[i-1][j][k][1][1][1]; } for(int p=0;p<lmt[i];p++){ if(p==8) continue; dp[i][k][p][1][2][0]+=dp[i-1][j][k][1][2][1]; } // == R for(int p=lmt[i];p<=lmt[i];p++) dp[i][k][p][h(j,k,p)][f(p)][1]+=dp[i-1][j][k][0][0][1]; for(int p=lmt[i];p<=lmt[i];p++){ if(p==4) continue; dp[i][k][p][h(j,k,p)][1][1]+=dp[i-1][j][k][0][1][1]; } for(int p=lmt[i];p<=lmt[i];p++){ if(p==8) continue; dp[i][k][p][h(j,k,p)][2][1]+=dp[i-1][j][k][0][2][1]; } for(int p=lmt[i];p<=lmt[i];p++) dp[i][k][p][1][f(p)][1]+=dp[i-1][j][k][1][0][1]; for(int p=lmt[i];p<=lmt[i];p++){ if(p==4) continue; dp[i][k][p][1][1][1]+=dp[i-1][j][k][1][1][1]; } for(int p=lmt[i];p<=lmt[i];p++){ if(p==8) continue; dp[i][k][p][1][2][1]+=dp[i-1][j][k][1][2][1]; } } } LL ret=0; for(int j=0;j<=9;j++) for(int k=0;k<=9;k++) for(int t=0;t<3;t++) for(int d=0;d<2;d++) ret+=dp [j][k][1][t][d]; return ret; } int main() { //freopen("number.in","r",stdin); //freopen("number.out","w",stdout); LL L,R; scanf("%lld%lld",&L,&R); printf("%lld\n",DP(R)-DP(L-1)); return 0; }
相关文章推荐
- 多线程开发和Socket技术
- CodeForce 628B New Skateboard 水题
- 对前端的一点小理解
- 使用图灵机器人高速开发智能聊天机器人
- Http请求头探讨
- 多级城市联动
- 133. Clone Graph
- Java基础知识:equals;有参无参
- Swift自定义初始化方法
- 软件工程结对作业02
- GCJ 2016 资格赛 C题
- Linux学习笔记12——配置ftp、squid、Tomcat、Samba、MySQL主从
- PHP面向对象编程--类的创建和对象实例化(类、对象、模块化、抽象)
- ArraryList知识
- 关于线程
- 【一周读书】用健康的法则而非道德的法则来规范我们世俗的欲望
- C++ STL 整理
- 第四次作业
- 孩子们的游戏(圆圈中最后剩下的数)
- 菱形的虚拟继承