BZOJ 4521 [CQOI2016]手机号码 - 数位DP

又是一道裸的数位DP,只不过状态有点多(小萌新表示看着好晕)


warn限制最大值。last,llast枚举上一位、上上一位的数值。d4,d8分别表示4与8是否出现过。tri表示前面状态是否存在三连数,最后到达边界时只有合法的tri为真才能给值。


此题尤为坑的一点是当l=1e10时会发现减一以后变成了10位数,则第一位必然为0,导致记忆化搜索无法进行,所以需要特判。


#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
long long l,r,cnt,ans;
int s[12];
long long dp[12][12][12][2][2][2][2];//dp数组记得开long long 
 
void init(long long x)
{
    cnt=0;
    while(x)s[++cnt]=x%10,x/=10;
}
long long Search(int len,int last,int llast,bool warn,bool d4,bool d8,bool tri)
{
    long long &res=dp[len][last][llast][warn][d4][d8][tri];
     
    if(res!=-1)return res;
    if(len==0)return res=tri?1:0;
     
    res=0;
     
    for(int i=len==11?1:0;i<10;i++)
    {
        if(warn&&i>s[len])break;
        bool nextd4=(d4||i==4),nextd8=(d8||i==8),nextwarn,nexttri;
 
        if(nextd4&nextd8)continue;
         
        nextwarn=warn&&i==s[len]?true:false;
        nexttri=(tri||(llast==last&&last==i))?true:false;
         
        res+=Search(len-1,i,last,nextwarn,nextd4,nextd8,nexttri);
    }
    return res;
}
 
int main()
{
    scanf("%lld%lld",&l,&r);
     
    memset(dp,-1,sizeof dp);
    init(r);
    ans+=Search(11,0,0,1,0,0,0);
     
    memset(dp,-1,sizeof dp);
    init(--l);
    if(l>10000000000)ans-=Search(11,0,0,1,0,0,0);
    //特判l==1e10
      
    printf("%lld",ans);
    return 0;
}


Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值