题面

传送门:洛咕


Solution

感谢神仙@lizbaka的教学

这题是数位DP的非常非常模板的题目,只是状态有点多

.

这题我使用记忆化搜索实现的

中国有句古话说的好,有多少个要求就设多少个状态。

所以说,考虑这样设置状态:

设\(f[i][j][k][2][2][2][2][2]\)表示当前填到第i位,上一位填了j,上两位填了k,是否卡上界,上一个数是否为前导零,是否有4,是否有8,是否出现了连续三个相同的数字,之后任意填的可行方案总数

使用记忆化搜索的话,转移是非常容易的,我们只需要像写搜索一样递归写下去就好

差不多长成这样:

for(int i=0;i<=(limit==true?l[to]:9);i++)
{
if(zero==false or i!=0)
t_ans+=dfs(to+1,i,last1,limit==true and i==l[to],false,four or i==4,eight or i==8,ok==true or(last1==last2 and last2==i));
else
t_ans+=dfs(to+1,i,last1,limit==true and i==l[to],true,false,false,false);
}

注:此题不用讨论前导零,但是我为了模板的完整性,也加上了。

注意,递归算法一定要有出口,这里也不例外,出口为i==n+1(即已经填完了)

具体写法还请看代码


Code

//Luogu P4124 [CQOI2016]手机号码
//Jan,13rd,2019
//测试递归实现数位DP
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=20;
long long f[N][15][15][2][2][2][2][2];//位数,上一位,上两位,limit,zero,4,8,OK
int n,l[N];
long long dfs(int to,int last1,int last2,bool limit,bool zero,bool four,bool eight,bool ok)
{
if(f[to][last1][last2][limit][zero][four][eight][ok]>=0)
return f[to][last1][last2][limit][zero][four][eight][ok];
long long t_ans=0;
if(to==n+1)
{
if((four and eight)==false and ok==true)
t_ans=1;
return f[to][last1][last2][limit][zero][four][eight][ok]=t_ans;
}
for(int i=0;i<=(limit==true?l[to]:9);i++)
{
if(zero==false or i!=0)
t_ans+=dfs(to+1,i,last1,limit==true and i==l[to],false,four or i==4,eight or i==8,ok==true or(last1==last2 and last2==i));
else
t_ans+=dfs(to+1,i,last1,limit==true and i==l[to],true,false,false,false);
}
return f[to][last1][last2][limit][zero][four][eight][ok]=t_ans;
}
int main()
{
long long ans[3];
for(int i=1;i<=2;i++)
{
long long t_num;
scanf("%lld",&t_num);
if(i==1) t_num--;
n=0;
while(t_num!=0)
l[++n]=t_num%10,t_num/=10;
reverse(l+1,l+1+n); memset(f,0x80,sizeof f);
dfs(1,0,0,true,true,false,false,false); ans[i]=f[1][0][0][true][true][false][false][false];
} printf("%lld",ans[2]-ans[1]);
return 0;
}

最新文章

  1. EF事务
  2. R语言绘图高质量输出
  3. .NET Framework 4.5 的五大特性
  4. 使用python + tornado 做项目demo演示模板
  5. STM32 UART 重映射
  6. Qt学习总结-ui篇
  7. G711
  8. vue学习笔记 样式 class style(五)
  9. 九九乘法表实现---基于python
  10. android 通过getDimension,getDimensionPixelOffset和getDimensionPixelSize获取dimens.xml文件里面的变量值
  11. 活代码LINQ——04
  12. 访问arcserver中的featureServer服务
  13. IdentityServer4【Introduction】之概括
  14. ubuntu16.04安装nvidia驱动及CUDA+cudnn
  15. LeetCode算法题(长期更新)
  16. Linux 中常用的命令
  17. pip install GitHub package
  18. 解决IDEA查看源码时提示:Library source does not match the bytecode for class的问题分析
  19. 05-python基础
  20. OAuth2.0网页授权 提示未关注该测试号

热门文章

  1. MySQL 5.7二进制日志
  2. Windows10下JDK8的下载安装与环境变量的配置
  3. Book of Shaders 00 - 使用 VS Code 编写 GLSL
  4. 电机AB相编码器测速
  5. vue 组件的封装
  6. FreeType2使用总结(转)
  7. DM9000裸机驱动程序设计
  8. 【转载】动态规划—各种 DP 优化
  9. jenkins:用jenkins通过ssh部署jar包到远程linux机器(jdk 15 / jenkins 2.257)
  10. spring boot:actuator的安全配置:使用spring security做ip地址限制(spring boot 2.3.2)