[Luogu P4124] [CQOI2016]手机号码 (数位DP)
2024-10-18 18:30:21
题面
传送门:洛咕
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;
}
最新文章
- EF事务
- R语言绘图高质量输出
- .NET Framework 4.5 的五大特性
- 使用python + tornado 做项目demo演示模板
- STM32 UART 重映射
- Qt学习总结-ui篇
- G711
- vue学习笔记 样式 class style(五)
- 九九乘法表实现---基于python
- android 通过getDimension,getDimensionPixelOffset和getDimensionPixelSize获取dimens.xml文件里面的变量值
- 活代码LINQ——04
- 访问arcserver中的featureServer服务
- IdentityServer4【Introduction】之概括
- ubuntu16.04安装nvidia驱动及CUDA+cudnn
- LeetCode算法题(长期更新)
- Linux 中常用的命令
- pip install GitHub package
- 解决IDEA查看源码时提示:Library source does not match the bytecode for class的问题分析
- 05-python基础
- OAuth2.0网页授权 提示未关注该测试号
热门文章
- MySQL 5.7二进制日志
- Windows10下JDK8的下载安装与环境变量的配置
- Book of Shaders 00 - 使用 VS Code 编写 GLSL
- 电机AB相编码器测速
- vue 组件的封装
- FreeType2使用总结(转)
- DM9000裸机驱动程序设计
- 【转载】动态规划—各种 DP 优化
- jenkins:用jenkins通过ssh部署jar包到远程linux机器(jdk 15 / jenkins 2.257)
- spring boot:actuator的安全配置:使用spring security做ip地址限制(spring boot 2.3.2)