HDU-6156 Palindrome Function(数位DP)
一、题目
二、思路
1、这是很明显的数位DP;
2、和以往数位DP不同的是,这里带了个进制进来,而以往做是纯十进制下或者纯二进制下做操作。但是,不管多少进制,原理都是一样的;
3、这里有个小坑,题目中说大于10的数用A、B、C、……、Z表示,那都是骗人的。分解给定数字的每一位数后,得到每一位的就是在给定进制下的该位的权值,压根不需要在数字、字母之间转来转去,纯数字娱乐;
4、比较直观的想法是:
(1)枚举给定范围内的每一个进制;
(2)计算在b进制下的回文数个数,然后即可得出在b进制下的和;
(3)累加上面的所有和,得出最终答案。
5、在4(2)中,利用数位DP计算在b进制下的回文数个数,需要记忆化。如何记忆化,怎么表示状态,这个是本题的关键所在。首先,当前搜索状态在数位中的位置pos,进制b,这个是确定状态的两个依据,不难想到。接下来,先把dp数组的设计放下来,看看dfs函数。既然与回文数有关,那自然,回文序列的起始位置start应该知道,因为前导0是不参与回文计算的。还有一点非常关键:因为要判断一个数是否回文,就必须从端点到中间扫描整个数字序列,而如果要这么做,那我们的记忆化就玩完了,每个数都判断一下,就变成暴力枚举了。所以,要让判断在搜索过程中完成。因此,需要使用一个数组,记录搜索的数字序列。注意,判断这个数字序列是不是回文的一定不是在一个数字所有位搜索完成之后再判断的,否则,就无法记忆化了。因为我们记录了数字序列最高位的起始位置,所以,在搜索过程中,当当前位置<=数字序列中点(start + 1) / 2时,开始做“回文比较”。如果当前已比较的数位对称了,继续比较下一位。当前已比较的数位对称的意思是,形如1213031……的数字序列,假设0所在的位置是这个数字序列的中心点。当当前搜索完省略号“……”前的一个1时,省略号前的31已经和0前面的13形成回文了,就是我所说的数位对称了。当下次使用数字序列3456065……的数字序列再次到达这个状态(注意,我们目前已确定的三个状态标志是,当前搜索状态在数位中的位置pos、进制b、回文序列的起始位置start)时,之后的操作完全和使用之前的序列1213031……到达这个状态后的操作一样。为什么呢?对于第一个数字序列1213031……而言,不管31之后的两位数(因为我们假设了数字序列的中心点是0的所在位置,所以,后面省略号部分其实只有两位,对应前面的12)是什么,肯定能找到21和前面的12对称。同样的道理,对于第二个数字序列3456065……而言,搜索省略号前的5这个位置后,不管后面省略号部分是什么,我总能找到一个43和前面的34对称。所以,在前面的1213031……的序列中,搜索完省略号部分后,当序列3456065……到达这个状态时,直接使用前面记忆化的结果即可,而无需再次向下搜索。这时有个比较疑惑的地方:如果后面省略号部分无法到达43呢,比如说,搜索上界就是345606540。注意,如果有上界限制,我们的程序是不会使用记忆化的结果的。所以,从前面的讨论来看,确定一个状态,还需要一个东西,当前已搜索过的序列是否构成回文串。比如前面的例子,1213031……,从中心点0位置开始,0 == 0,搜索下一位,0后面的3 == 0前面的3,0后面的1 == 0前面的3前面的1……,搜索完这个状态后,当前已搜索过的序列是已经构成回文串的。同样地,如果序列是1213032……,当比较省略号前的2和0前面的3前面的1时,发现不相等,那后面如何,这个序列都不会是回文串了。但是,这也是一种状态,记忆化时需要区分开。所以,说了这么多,可以确定记忆化数组dp的四个状态标志了:①当前搜索状态在数位中的位置pos、②进制b、③回文序列的起始位置start、④搜索到当前位置时,之前搜索过的序列是否已经部分回文。这里的第④个标志特别要注意,已部分回文,不是这样的,11011……(认为这里的11011是回文的)。而是,从这个数字序列的中心位置开始,是否每一位都和其对应位相等。如果是,那么,那就满足④,是已部分回文的。注意,一定要到达中心位置后才能开始判断。
三、注意点
1、这题不需要把前导0作为限制条件加到dfs函数中,有了pos和start就行了。否则,很多本可以记忆化的,加了!lead限制条件后,不能使用记忆化结果,也不能记忆化搜索值。效率大大降低。导致代码在HDU上超时。
2、我用这个测试样例(http://public-1252154746.cosgz.myqcloud.com/acmdata/hdu6156input.txt),加了前导0的限制条件,耗时11s左右。不加该条件,耗时5s左右。在HDUOJ上运行耗时2100ms左右。对应的输出文件:http://public-1252154746.cosgz.myqcloud.com/acmdata/hdu6156output.txt。
四、源代码
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long LL; LL dp[][][][];//注意,因为最小进制为2,所以,pos最大可能是30(因为x和y最大是1e9),要确保大小足够。 ], dn, bit[]; template <class T> inline void read(T &x) { int t; bool flag = false; ')) ; if(t == '-') flag = true, t = getchar(); x = t - '; + t - '; if(flag) x = -x; } LL dfs(int pos, int base, int start, bool ispd, bool limit) { )return ispd; )return dp[pos][base][start][ispd]; ; LL ans = ; ; i <= top; ++i) { bit[pos] = i; )ans += dfs(pos - , , ispd, limit && i == top); else { ) >> ; , base, start, ispd, limit && i == top); , ], limit && i == top); /**else这里的第4个参数不需要ispd && i == bit[start - pos + 1],因为只要某位和对应位不相等, 那么之后的搜索都会从前面的if中进去。*/ } } if(!limit)dp[pos][base][start][ispd] = ans; return ans; } LL solve(LL n, int b) { dn = ; ) { digit[++dn] = n % b; n /= b; } return dfs(dn, b, dn, true, true); } int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif LL L, R, l, r, T, ans; memset(dp, -, sizeof(dp)); scanf("%lld", &T); ; t <= T; ++t) { ans = ; read(L), read(R), read(l), read(r); for(int b = l; b <= r; ++b) { LL ans1 = solve(R, b), ans2 = solve(L - , b); ans += (ans1 - ans2) * b + (R - L + - (ans1 - ans2)); } printf("Case #%lld: %lld\n", t, ans); } ; }
HDU-6156 Palindrome Function(数位DP)的更多相关文章
- HDU 6156 - Palindrome Function [ 数位DP ] | 2017 中国大学生程序设计竞赛 - 网络选拔赛
普通的数位DP计算回文串个数 /* HDU 6156 - Palindrome Function [ 数位DP ] | 2017 中国大学生程序设计竞赛 - 网络选拔赛 2-36进制下回文串个数 */ ...
- HDU 6156 Palindrome Function(数位DP)题解
思路: 数位dp的操作是dfs+记忆化,我们dp开四维:位置,长度,进制,是否回文.然后每次暴搜记录下每个位置的数字是什么,搜到对称轴另一边需要检查是否符合回文. 终于把友谊赛的题目都补完了...没做 ...
- HDU 6156 Palindrome Function
http://acm.hdu.edu.cn/showproblem.php?pid=6156 题意:$f(n,k)$表示判断n在k进制下是否是回文串,如果是,则返回k,如果不是,则返回1.现在要计算$ ...
- HDU 6156 回文 数位DP(2017CCPC)
Palindrome Function Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 256000/256000 K (Java/Ot ...
- 【数位DP】HDU 6156 Palindrome Function
http://acm.hdu.edu.cn/showproblem.php?pid=6156 [AC] #include<bits/stdc++.h> using namespace st ...
- hdu 5898 odd-even number 数位DP
传送门:hdu 5898 odd-even number 思路:数位DP,套着数位DP的模板搞一发就可以了不过要注意前导0的处理,dp[pos][pre][status][ze] pos:当前处理的位 ...
- hdu 5106 Bits Problem(数位dp)
题目链接:hdu 5106 Bits Problem 题目大意:给定n和r,要求算出[0,r)之间全部n-onebit数的和. 解题思路:数位dp,一个ct表示个数,dp表示和,然后就剩下普通的数位d ...
- HDU 2089 - 不要62 - [数位DP][入门题]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 Time Limit: 1000/1000 MS (Java/Others) Memory Li ...
- HDU 5179 beautiful number 数位dp
题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5179 bc(中文): http://bestcoder.hdu.edu.cn/contes ...
随机推荐
- LA 4253 箭术(二分枚举)
https://vjudge.net/problem/UVALive-4253 题意: 有n个平行于x轴的线段,每条线段代表一个靶子.判断是否可以站在x轴上[0,W]区间内的某个位置射箭. 思路:二分 ...
- python 简单的猜数字游戏
!/usr/bin/env python --encoding:utf-8-- import random think=random.randint(1,10) print ("...... ...
- 用PHP开发命令行工具
介绍 用过laravel开发过项目的都应该用过artisan,通过artisan我们可以在命令行中创建控制器类,Eloquent类等,今天我们将通过php来开发命令行工具 开发环境与工具 使用vagr ...
- 【源码学习之spark streaming 1.6.1 】
说明:个人原创,转载请说明出处 http://www.cnblogs.com/piaolingzxh/p/5634577.html 未完待续
- ping 原理与ICMP协议[转]
原文:http://blog.csdn.net/inject2006/article/details/2139149 ping 的原理 ping 程序是用来探测主机到主机之间是否可通信,如果不 ...
- rails5.2新特性--ActiveStorage, 使用80percent/rails-template
看guide,看ruby-China的好贴,看最新版的书上案例. 以下摘自https://ruby-china.org/topics/36666 作者lyfi2003 用户对上传文件的要求体验: 上传 ...
- bzoj2705: [SDOI2012]Longge的问题 欧拉定理
题意:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N). 题解:考虑n的所有因子,假设有因子k,那么对答案的贡献gcd(i,n)==k的个数即gcd(i/k,n/k)== ...
- Wannafly挑战赛15-C-出队
链接:https://www.nowcoder.com/acm/contest/112/C来源:牛客网 约瑟夫问题(https://baike.baidu.com/item/约瑟夫问题),n个人,1 ...
- HDU 4633 Who's Aunt Zhang ★(Polya定理 + 除法取模)
题意 用K个颜色给魔方染色,魔方只能整体旋转并且旋转重合的方案算一种,求一共有多少不同的染色方案. 思路 经典的Polya应用,记住正六面体的置换群就可以了,魔方就是每个大面变成9个小面了而已: 本题 ...
- Bayes' theorem (贝叶斯定理)
前言 AI时代的到来一下子让人感觉到数学知识有些捉襟见肘,为了不被这个时代淘汰,我们需要不断的学习再学习.其中最常见的就是贝叶斯定理,这个定理最早由托马斯·贝叶斯提出. 贝叶斯方法的诞生源于他生前为解 ...