51nod 1009 数位dp入门

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1009

1009 数字1的数量

基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题

收藏

关注

给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数。

例如:n = 12,包含了5个1。1,10,12共包含3个1,11包含2个1,总共5个1。

Input

输入N(1 <= N <= 10^9)

Output

输出包含1的个数

Input示例

12

Output示例

5第一次写数位dp还是挺头疼的啊,dp[i][j]表示以j开头的i位数x=(j+1)*pow(10,i-1)-1,1-x之间所有的数中1出现的次数。不难写出方程 dp[i][j]=dp[i][j-1]+dp[i-1][9]  这个自己模拟一下就知道了,特殊的对于 dp[i][0]=dp[i-1][9] ;当j==1时上面的方程也要变化为 dp[i][1]=dp[i][j-1]*2+pow(10,i-1),这是因为最高位的‘1‘不能被忽略之后对于每次询问的数将他依次拆解计算,例如对于N=3456,我们先拆出来 [1,2999],也就是 dp[4][2] ,容易发现剩下的数就是 3000-3456,但是3!=1,所以这一段<==> 1-456,这样每次计算一位就ok,特殊的对于出现1的位置例如 1234,我们加上dp[4][0]之后剩下的数是 1000-1234,这个1显然不能抛弃,我们加上234+1个‘1‘之后再把数转化为 1-234计算就好了。第一次写所以写了个暴力对拍!
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 LL mod=1e9+7;
 5 LL dp[15][15];
 6 LL qpow(int,int);
 7 LL bruce(int a,int b)
 8 {
 9     LL s=0;
10     for(int i=a;i<=b;++i)
11     {
12         int n=i;
13         while(n){
14             if(n%10==1) s++;
15             n/=10;
16         }
17     }
18     return s;
19 }
20 LL qpow(int a,int b)
21 {
22     LL r=1;
23     while(b){
24         if(b&1) r=r*a;
25         a*=a;
26         b>>=1;
27     }
28     return r;
29 }
30 int main()
31 {
32     int N,i,j,k;
33     for(i=1;i<=9;++i) dp[1][i]=1;
34     for(i=2;i<=10;++i)
35     {
36         dp[i][0]=dp[i-1][9];
37         for(j=1;j<=9;++j)
38         {
39             if(j!=1) dp[i][j]=dp[i][j-1]+dp[i-1][9];
40             else dp[i][j]=2*dp[i][j-1]+qpow(10,i-1);
41            // cout<<i<<‘ ‘<<j<<‘ ‘<<dp[i][j]<<‘ ‘<<bruce(j,i)<<endl;
42         }
43
44     }
45     cin>>N;int nn=N;
46     LL bit=0,s=0,len=log(N+0.5)/log(10)+1;
47     for(i=len;i>=1;--i)
48     {
49         int mul=qpow(10,i-1);
50         int bit_num=N/mul;
51         s+=dp[i][bit_num-1];
52         N%=mul;
53         if(bit_num==1) s+=N+1;
54        // cout<<"s="<<s<<endl;
55     }
56     cout<<s<<endl;
57     return 0;
58 }
时间: 2024-10-30 06:06:16

51nod 1009 数位dp入门的相关文章

HDU 2089 不要62 数位DP入门

Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众.不吉利的数字为所有含有4或62的号码.例如:62315 73418 88914都属于不吉利号码.但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列.你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多

数位DP入门题 hdu 2089 hdu 3555

hdu 2089 不要62 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意:对于每次给出的一个区间,找出区间内多少个数字没有出现62和4. 思路: 数位DP入门题,对于dfs设置3个参数. 一个表示现在进行到第几位, 一个表示前一个标记状态,这里表示上一位是不是6. 一个表示是否现在是这位可以取到的最大的数字. 如果上一位是6,那么这位不可以取2.且当前位都不可以取4. 1 #include <bits/stdc++.h> 2 us

xbz分组题B 吉利数字 数位dp入门

B吉利数字时限:1s [题目描述]算卦大湿biboyouyun最近得出一个神奇的结论,如果一个数字,它的各个数位相加能够被10整除,则称它为吉利数.现在叫你计算某个区间内有多少个吉利数字. [输入]第一行为样例个数N.接下来N行,每一行代表一个输入样例,每个输入样例有2个数,分别代表某个区间的起点a和终点b.注意所求区间为[a,b],1<=a<=b<=10^9 [输出]N行.对于第x个输入样例,在第x行输入该样例所对应的结果. [输入样例]21 101 20 [输出样例]01 [Hint

HDU 2089 不要62【数位DP入门题】

不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 56193    Accepted Submission(s): 21755 Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可

HDU 2089 不要62(数位dp入门)

题意:统计区间 [a,b] 中不含 4 和 62 的数字有多少个. 题解:这是数位DP的入门题了,首先要理解数DP的原理,DP[i][j]:代表第i位的第j值,举个栗子:如4715   数位数是从右向左的,则第一位是5,第二位是1,第三位是7,第四位是4.所以如果要求0到4715,ans=dp[4][x]+dp[3][y]+dp[2][z]+dp[1][k] 0<=x<=4(但是4要去掉),0<=y<=9,0<=z<=9,0<=k<=9(还要注意判断,把其中

HDU ACM 4734 F(x)-&gt;数位DP入门练习题

分析:数位DP的入门联系题,通过该題对数位DP有感觉了:dp[len][presum]代表长度为len权值不大于presum的数.记忆化搜索提高效率,除边界(因为边界上算出来的答案在其它数中可能是不完整的)外记录dp[len][presum]的值,下次发现以前计算过就直接return:dfs(len, presum, fg)表示求长度为len,不超过pre的全部符合条件的值.fg是控制边界的. #include<iostream> using namespace std; int dp[11]

HDU-2089不要62-暴力或数位DP入门

不要62 题意:给定区间,求在这个区间中有多少个数字,不包含4且不包含62: 这道题作为数位DP的入门题: 暴力也是可以过 #include<cstdio> #include <iostream> #include <cstring> #include <string> #include <algorithm> using namespace std; const int maxn =1e6+7; int a[maxn]; bool check(

数位DP入门:bzoj1833: [ZJOI2010]count 数字计数

膜拜了一下蔡大神....然后突然想起来一些东西然后就填了一个半年多前的坑= = 人生第一道自己写的数位DP...好吧以前是看题解然后也不知道为什么就过了的>_< 数位DP介绍: http://wenku.baidu.com/link?url=9OS5Ybpw5wx00ahrH8ED2oyIlR1uWwrxT8N4pEg27GgBt2T2hLe4sd_h1rmpY7P0HmeHIEDw9h6_K98dPhhjoMhD2TpKcS8w1X8cC_dkPp_ 接下来是题目地址: http://www

数位DP入门

数位DP其实是很灵活的,所以一定不要奢求一篇文章就会遍所有数位DP的题,这一篇只能是讲清楚一种情况,其他情况遇到再总结,在不断总结中慢慢体会这个思想,以后说不定就能达到一看到题目就能灵活运用的水平.(其实DP都是这样……) 这一篇要说的数位DP是一道最简单的数位DP:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题目大意:多组数据,每次给定区间[n,m],求在n到m中没有“62“或“4“的数的个数. 如62315包含62,88914包含4,这两个数