【洛谷P4124】[CQOI2016]手机号码

本文介绍了一道关于手机号码的数字动态规划(DP)模板题,并提供了详细的记忆化搜索解决方案。通过递归函数实现,考虑了数字重复、特定数字出现的限制条件,最终计算出符合条件的电话号码数量。

手机号码

数位DP模板题

记忆化搜索:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define int long long
int L,R,Maxx[15],dp[15][2][15][2][2][2];
int dfs(int len,bool ok,int last,bool same,bool four,bool eight,bool shangxian)
//剩余的位数,是否已经有三个连续相同的数字,上一个数字,上一个数是否与上上个数字相同,是否有4,是否有8,是否是上限值 {
if(len==0) return (int)ok; if(!shangxian&&dp[len][ok][last][same][four][eight]!=-1) return dp[len][ok][last][same][four][eight]; int M=shangxian?Maxx[len]:9,cnt=0; for(int i=0;i<=M;i++){ if((four&&i==8)||(eight&&i==4)||(len==11&&i==0)) continue; cnt+=dfs(len-1,ok||(same&&last==i),i,last==i,four||i==4,eight||i==8,shangxian&&i==M); } if(!shangxian) dp[len][ok][last][same][four][eight]=cnt; return cnt; } int solve(int x){ int cnt=0; memset(dp,-1,sizeof(dp)); while(x){ Maxx[++cnt]=x%10; x/=10; } return dfs(11,0,-1,0,0,0,1); } #undef int int main() #define int long long { scanf("%lld%lld",&L,&R); int B=solve(L-1); int A=solve(R); printf("%lld\n",A-B); return 0; }

 

转载于:https://www.cnblogs.com/yjkhhh/p/9261597.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值