热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

2022杭电多校七FSumire(数位DP+实用技巧)

题目链接:杭电多校7-VirtualJudgevjudge上题目显示的有问题,我下面附上官方题目:样例输入:32201

题目链接:杭电多校7 - Virtual Judge

vjudge上题目显示的有问题,我下面附上官方题目:

样例输入: 

3
2 2 0 1 5
1 4 3 11 45
10 14 11 19 198

样例输出:

6
19
1049

题意:多组样例,每组样例给出五个数k,b,d,l,r,其中b是代表b进制,f(i,b,d)代表在b进制下i的数位中出现数字d的个数。求

 分析:定义f[i][j][1/0][1/0]表示已经统计了前i位有j位是d且当前位有/无限制,有/无前导0的方案数

一开始我按照普通的数位DP思路求解,但是总是超时,然后仔细分析了一下,发现了原来的数位DP还可以具体根据题目优化一下。

比如这道题,我一开始是分两种情况来进行动态转移:

枚举当前填的数字

一种情况是当前有前导0且当前位置填0。

另一种情况就是当前位置填无前导0或者当前位置不填0,这两个合成一种情况即可。

dfs代码是这样写的:

long long dfs(int pos,int cnt,int limit,int lead)
{if(pos&#61;&#61;0) return (cnt&#61;&#61;tt);if(!limit&&!lead&&f[pos][cnt]!&#61;-1) return f[pos][cnt];int up&#61;limit?a[pos]:(b-1);long long ans&#61;0;for(int i&#61;0;i<&#61;up;i&#43;&#43;){if(lead&&i&#61;&#61;0) ans&#43;&#61;dfs(pos-1,cnt,limit&&(i&#61;&#61;a[pos]),lead);else ans&#43;&#61;dfs(pos-1,cnt&#43;(i&#61;&#61;d),limit&&(i&#61;&#61;a[pos]),0); }if(!limit&&!lead) f[pos][cnt]&#61;ans;return ans;
}

后来对这样的代码进行了很多优化发现还是超时&#xff0c;仔细分析了一下才发现当前位置如果不填d或者up或者0&#xff0c;那么填其他任何数字都是一样的&#xff0c;因为只有d才会对最后的答案造成影响&#xff0c;而up会对下一次可以取的数字造成影响&#xff0c;而0可以对前导0造成影响&#xff0c;所以对于一种情况&#xff0c;如果我们可以在0~up中做出选择&#xff0c;去掉d、up、0之外的数选哪个都是一样的&#xff0c;我们可以直接计算一下这样的数字的个数&#xff0c;然后直接令ans&#43;可选数字个数*dfs(pos-1&#xff0c;cnt&#xff0c;0&#xff0c;0)即可&#xff0c;因为选的数既不是上限也不是0&#xff0c;所以会去掉限制和前导0&#xff0c;而且由于选的数不是d&#xff0c;那么也不会对答案造成贡献&#xff0c;所以我们就可以把很多次重复的计算直接一次算出来&#xff0c;这样的话就会极大地优化时间&#xff0c;从而就可以ac&#xff0c;有同学可能会问&#xff1a;我们都记忆化了&#xff0c;算一次和算十次有什么本质区别吗&#xff0c;算完一次之后再算就直接访问数组就可以了啊&#xff0c;为什么这样还会节省时间呢&#xff1f;可以这么想假如说我们刚才讨论的那种不是up和d和0的情况有10000种&#xff0c;那么我们就需要访问10000次数组&#xff0c;这样算下来复杂度会高很多&#xff0c;而我们之前的数位DP题目一般进制数都很少&#xff0c;或者说一般都是10进制的&#xff0c;而这道题b的上界是1e9&#xff0c;这个数还是很大的&#xff0c;所以我们这种优化对于进制数比较大的问题还是很有用的。

这个技巧近适用于贡献与某位数字有直接关系的题目中。

细节见代码&#xff1a;

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
long long k,b,d;
const int N&#61;65,mod&#61;1e9&#43;7;
long long f[N][N][2][2];//f[i][j][1/0][1/0]表示已经统计了前i位有j位是d且当前位有/无限制&#xff0c;有/无前导0的方案数
long long a[N],tt;
long long qpow(long long a,long long b)
{if(a&#61;&#61;0) return 0;//题目中要求0^0&#61;0long long ans&#61;1;while(b){if(b&1) ans&#61;ans*a%mod;a&#61;a*a%mod;b>>&#61;1;}return ans;
}
long long dfs(int pos,int cnt,int limit,int lead)
{if(!pos) return qpow(cnt,k);if(f[pos][cnt][limit][lead]!&#61;-1) return f[pos][cnt][limit][lead];int up&#61;limit?a[pos]:(b-1);long long ans&#61;0;if(d&#61;&#61;up){if(lead){ans&#43;&#61;dfs(pos-1,cnt,0,1);//有前导0且填0ans&#43;&#61;dfs(pos-1,cnt&#43;1,limit,0);//有前导0填d ans&#43;&#61;(up-1)*dfs(pos-1,cnt,0,0)%mod;//有前导0但不填up和0 }else{ans&#43;&#61;dfs(pos-1,cnt&#43;1,limit,0);//无前导0填dans&#43;&#61;up*dfs(pos-1,cnt,0,0)%mod;//无前导0但不填d} ans%&#61;mod;}else if(d&#61;&#61;0){if(lead){ans&#43;&#61;dfs(pos-1,cnt,0,1);//有前导0且填0ans&#43;&#61;dfs(pos-1,cnt,limit,0);//有前导0且填upans&#43;&#61;(up-1)*dfs(pos-1,cnt,0,0)%mod;//有前导0但不填up和d }else{ans&#43;&#61;dfs(pos-1,cnt&#43;1,0,0);//无前导0且填dans&#43;&#61;dfs(pos-1,cnt,limit,0);//无前导0且填upans&#43;&#61;(up-1)*dfs(pos-1,cnt,0,0)%mod;//无前导0且不填up和d } ans%&#61;mod;}else if(up>d)//d不等于up和0,但是要保证up大于d {if(lead){ans&#43;&#61;dfs(pos-1,cnt,0,1);//有前导0且填0ans&#43;&#61;dfs(pos-1,cnt&#43;1,0,0);//有前导0且填dans&#43;&#61;dfs(pos-1,cnt,limit,0);//有前导0且填upans&#43;&#61;(up-2)*dfs(pos-1,cnt,0,0)%mod;//有前导0但不填up和d和0 }else{ans&#43;&#61;dfs(pos-1,cnt&#43;1,0,0);//无前导0且填dans&#43;&#61;dfs(pos-1,cnt,limit,0);//无前导0且填upans&#43;&#61;(up-1)*dfs(pos-1,cnt,0,0)%mod;//无前导0但不填up和d} ans%&#61;mod;}else//up}
long long solve(long long x)
{memset(f,-1,sizeof f);int pos&#61;0;while(x){a[&#43;&#43;pos]&#61;x%b;x/&#61;b;}return dfs(pos,0,1,1);
}
int main()
{int T;cin>>T;long long l,r;while(T--){scanf("%lld%lld%lld%lld%lld",&k,&b,&d,&l,&r);printf("%lld\n",(solve(r)-solve(l-1)&#43;mod)%mod);}return 0;
}


推荐阅读
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
  • 本文基于刘洪波老师的《英文词根词缀精讲》,深入探讨了多个重要词根词缀的起源及其相关词汇,帮助读者更好地理解和记忆英语单词。 ... [详细]
  • 数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
    本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • Docker的安全基准
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • PyCharm下载与安装指南
    本文详细介绍如何从官方渠道下载并安装PyCharm集成开发环境(IDE),涵盖Windows、macOS和Linux系统,同时提供详细的安装步骤及配置建议。 ... [详细]
  • 在 Windows 10 中,F1 至 F12 键默认设置为快捷功能键。本文将介绍几种有效方法来禁用这些快捷键,并恢复其标准功能键的作用。请注意,部分笔记本电脑的快捷键可能无法完全关闭。 ... [详细]
  • 本文介绍了如何使用JQuery实现省市二级联动和表单验证。首先,通过change事件监听用户选择的省份,并动态加载对应的城市列表。其次,详细讲解了使用Validation插件进行表单验证的方法,包括内置规则、自定义规则及实时验证功能。 ... [详细]
  • 本文详细介绍了如何构建一个高效的UI管理系统,集中处理UI页面的打开、关闭、层级管理和页面跳转等问题。通过UIManager统一管理外部切换逻辑,实现功能逻辑分散化和代码复用,支持多人协作开发。 ... [详细]
author-avatar
捕风的默小墨
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有