HDU 2089 不要62

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=2089

Problem Description
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
 
Input
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
 
Output
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
 
Sample Input
1 100
0 0
 
Sample Output
80
 
 /*
问题
输入一对整数n和m(0<n≤m<1000000), 如果遇到的都是0的整数对表示输入结束
计算并输出有多少不含4和62(必须连号)的数字的个数 解题思路
首先的想法是将1000000以内的符合条件的数打表,然后在区间里数数就行了。
参考网上的解答,这是一道数位DP,那么问题来了什么是数位DP呢?
数位DP就是在根据每个数的各位数字的一些规律,能够得到一些递推关系,从而通过记忆化搜索来解决一些问题的思想。一般是区间内
满足条件的数有多少个,相对于暴力破解,数位DP的解题方法更巧妙,更简洁、高效。 拿不要62这道题来说,不吉利数字要么包含4,要么包含62(必须连号),反过来一个吉利数字需要不能有4,也不能有62
所以定义变量为i和j,表示数字的长度是i,最高位是j
那么状态就是f[i][j],表示数字的长度是i,最高位是j,符合条件的数有多少个
可以根据规律写出如下递推式:
f[i][j]=     if (j==4) f[i][j]=0     else if (j!=6) f[i][j]=Σf[i-1][k] (k=0,1,2,3,4,5,6,7,8,9)     else if (j==6) f[i][j]=Σf[i-1][k] (k=0,1,3,4,5,6,7,8,9) 有了这个二维表,我们只需要计算一个数x,0到x有多少个符合条件的数,最后左区间减去右区间几位答案。
参考博客:https://blog.csdn.net/zhangxian___/article/details/75304335
*/
#include<cstdio>
#include<cstring>
const int maxn=;
int f[maxn][maxn],c[maxn];
void getf();
long long solve(int n); int main()
{
int n,m;
getf(); while(scanf("%d%d",&n,&m) == && m+n != ){
long long a=solve(m+);
long long b=solve(n); printf("%lld\n",a-b);
}
return ;
} long long solve(int n)
{
int a[]={},i,j,k; i=;
while(n){
a[i++] = n%;
n/=;
}
/*for(j=1;j<i;j++)
printf("@%d ",a[j]);
printf("\n");*/
i--;//长度减一为最高位数字的下标 long long ans=;
for(k=i;k>=;k--){//枚举每一位数字的下标
for(j=;j<a[k];j++){//枚举0到每一位数字减一
if(j != && !(a[k+] == && j == )){
ans += f[k][j];
}
}
if(a[k] == ) break;
if(a[k+] == && a[k] == ) break;
}
return ans;
} void getf()
{
int i,j,k;
memset(f,,sizeof(int)*maxn*maxn);
f[][]=;//0位数最高位是0,初始化为1
for(i=;i<;i++){
for(j=;j<;j++){
if(j == ) f[i][j]=;
else if(j == )
{
for(k=;k<;k++)
f[i][j] += f[i-][k];
f[i][j] -= f[i-][];
}
else
{
for(k=;k<;k++)
f[i][j] += f[i-][k];
}
}
}
/*for(i=1;i<10;i++){
for(j=0;j<10;j++){
printf("%d ",f[i][j]);
}
printf("\n");
}*/
}

HDU 3555 Bomb

题意

给出一个N(1 <= N <= 2^63-1),问1到N中不含49序列的数字有多少个

解题思路

  类似这种含某个序列的数的个数,我们可以将其转换成不含某个序列的数,然后用总的个数减去即可。

我们用上面不含62的模板,求出1到N中不含49序列的数的个数,然后用总数减去。不同的是数组可能溢出,需要用long long 存储。

代码:

#include <cstdio>
#include <cstring> typedef long long ll;
const int maxn = ;
ll f[maxn][maxn]; void getf() {
memset(f, , sizeof(ll)*maxn*maxn);
f[][] = ;
for(int i = ; i < maxn; i++) {
for(int j = ; j < ; j++) {
for(int k = ; k < ; k++) {
f[i][j] += f[i - ][k];
}
if(j == )
f[i][j] -= f[i - ][];
}
}
} ll solve(ll x) {
int a[maxn] = {};
int i = ;
while(x) {
a[i++] = x%;
x /= ;
}
ll ans = ;
for(int k = i - ; k >= ; k--) {
for(int j = ; j < a[k]; j++) {
if(!(j == && a[k + ] == ))
ans += f[k][j];
}
if(a[k + ] == && a[k] == ) break;
}
return ans;
} int main()
{
ll n;
int T;
scanf("%d", &T);
while(T--) {
getf();
scanf("%I64d", &n);
printf("%I64d\n", n - solve(n + ) + );
}
return ;
}

递推、数位DP解析(以HDU 2089 和 HDU 3555 为例)的更多相关文章

  1. [Codeforces676B]Pyramid of Glasses(递推,DP)

    题目链接:http://codeforces.com/problemset/problem/676/B 递推,dp(i, j)表示第i层第j个杯子,从第一层开始向下倒,和数塔一样的题.每个杯子1个时间 ...

  2. 算法技巧讲解》关于对于递推形DP的前缀和优化

    这是在2016在长沙集训的第三天,一位学长讲解了“前缀和优化”这一技巧,并且他这一方法用的很6,个人觉得很有学习的必要. 这一技巧能使线性递推形DP的速度有着飞跃性的提升,从O(N2)优化到O(N)也 ...

  3. 2017"百度之星"程序设计大赛 - 复赛1003&&HDU 6146 Pokémon GO【数学,递推,dp】

    Pokémon GO Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. openjudge1768 最大子矩阵[二维前缀和or递推|DP]

    总时间限制:  1000ms 内存限制:  65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的 ...

  5. Uva 10446【递推,dp】

    UVa 10446 求(n,bcak)递归次数.自己推出来了一个式子: 其实就是这个式子,但是不知道该怎么写,怕递归写法超时.其实直接递推就好,边界条件易得C(0,back)=1.C(1,back)= ...

  6. 刷题向》关于一道比较优秀的递推型DP(openjudge9275)(EASY+)

    先甩出传送门:http://noi.openjudge.cn/ch0206/9275/ 这道题比较经典, 最好不要看题解!!!!! 当然,如果你执意要看我也没有办法 首先,显然的我们可以用 f [ i ...

  7. 洛谷4316 绿豆蛙的归宿(DAG递推/概率dp)

    题目大意: 给定一个DAG,求起点到终点的路径长度期望 根据题意可以知道每一条边都有一定概率被走到 那么\(\displaystyle\begin{aligned} Ans = \sum_{e \in ...

  8. hdu 4472 Count(递推即dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4472 代码: #include <cstdio> #include <cstring ...

  9. 数位DP入门(A - 不要62 HDU - 2089 &&B - Bomb HDU - 3555 )

    题目链接:https://cn.vjudge.net/contest/278036#problem/A 具体思路:对于给定的数,我们按照位数进行运算,枚举每一位上可能的数,在枚举的时候需要注意几个条件 ...

随机推荐

  1. kafka eagel的使用

    sql语句eq: select * from "ke_test_topic" where "partition" in (0,1,2) limit 100 官网 ...

  2. C#调用haskell遭遇Attempted to read or write protected memory

    1. Haskell的代码如下: 上面的代码中readMarkdown与writeHtmlString是pandoc中的函数,newString的作用是将String转换为IO CString. 2. ...

  3. spark-mllib 密集向量和稀疏向量

    spark-mllib 密集向量和稀疏向量 MLlib支持局部向量和矩阵存储在单台服务器,也支持存储于一个或者多个rdd的分布式矩阵 . 局部向量和局部矩阵是用作公共接口的最简单的数据模型. 基本的线 ...

  4. ubuntu18.10安装redis遇到问题

    执行命令apt-get install redis-server 安装遇到的问题 1.出现apt-get被占用情况,用ps -a|grep apt ,杀死存在的apt进程 2.还不行就执行sudo f ...

  5. 剑指offer编程题Java实现——面试题7用两个栈实现队列

    题目:用两个栈实现一个队列.队列的声明如下:请实现他的两个函数appendTail和deleteHead, 分别完成在队列尾部插入节点和在队列头部删除节点的功能. package Solution; ...

  6. 【BZOJ3709】 [PA2014]Bohater(贪心)

    传送门 BZOJ Solution 考虑如果可以回血肯定要打,那么就是按照伤害值从小到大排个序能打就打,不能打就\(NIE\). 接着看不能够回血的,emmm,把这个过程反着看一下就是打一个怪扣\(a ...

  7. 【BZOJ3097】 Hash Killer I

    BZOJ3097 Hash Killer I Solution 考虑它是自然溢出,相当于就是对\(2^{63}\)取膜 那么就有\(aaaaa...aaa\)(多于64个)和\(baaaa...aaa ...

  8. graphite custom functions

    尊重作者的劳动,转载请注明作者及原文地址 http://www.cnblogs.com/txwsqk/p/6522854.html 参考 https://graphite.readthedocs.io ...

  9. 01-Python的基础知识3

    - 数字 - 数字常量: - 整型: - 概念: - 指代平常数学上的整数常量.Python中整型指代int类型. - 基本运算: - 可以执行平常的+,-,*,/ ,%以及其他操作 假设a=15,b ...

  10. iframe 自适应高度和宽度

    <iframe src="pay/index.aspx" marginheight="0" marginwidth="0" frame ...