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,统计一下所有高位的1,乘上当前区间内数的个数。
 #include<bits/stdc++.h>
using namespace std;
int f[][];
int bit[];
int p10[]={};
int cal(int N){
int ans=,len=,ok=;
while(N){
bit[len++]=N%;
N/=;
}
bit[len]=-;
for(int i=len-;i>=;--i){
for(int k=;k<bit[i];++k){
ans+=f[i+][k];
int tot=;
for(int j=i+;j<len;j++){
if(bit[j]==){
tot++;
}
}
ans+=tot*p10[i];
}
}
return ans;
}
int main(){
int i,j,k;
for(i=;i<;++i) p10[i]=p10[i-]*;
f[][]=;
for(i=;i<=;++i){
for(j=;j<;++j){
for(k=;k<;++k){
f[i][j]+=f[i-][k];
}
if(j==) f[i][j]+=p10[i-];
}
} int N;
while(scanf("%d",&N)==)
printf("%d\n",cal(N+));
return ;
}

  f[i]表示所有的i位数中包含1的个数,有前导零的数也计算在内,因为在计算高位时低位可以为零。

 #include<bits/stdc++.h>
using namespace std;
#define LL long long
LL f[]={,};
LL p10[]={,};
int bit[];
void init(){
for(int i=;i<=;++i) p10[i]=p10[i-]*;
for(int i=;i<=;++i) f[i]=f[i-]*+p10[i-];
}
LL cal(int N){
int len=;
while(N){
bit[len++]=N%;
N/=;
}
bit[len]=-;
LL ans=,one=;
for(int i=len-;i>=;--i){
ans+=f[i]*bit[i];
if(bit[i]>) ans+=p10[i];
ans+=p10[i]*bit[i]*one;
if(bit[i]==) one++;
}
return ans;
}
int main(){
int n,i,j,k;
init();
while(scanf("%d",&n)==){
printf("%lld\n",cal(n+));
}
return ;
}

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

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

    B吉利数字时限:1s [题目描述]算卦大湿biboyouyun最近得出一个神奇的结论,如果一个数字,它的各个数位相加能够被10整除,则称它为吉利数.现在叫你计算某个区间内有多少个吉利数字. [输入]第 ...

  2. 数位dp入门 hdu2089 不要62

    数位dp入门 hdu2089 不要62 题意: 给定一个区间[n,m] (0< n ≤ m<1000000),找出不含4和'62'的数的个数 (ps:开始以为直接暴力可以..貌似可以,但是 ...

  3. hdu3555 Bomb 数位DP入门

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 简单的数位DP入门题目 思路和hdu2089基本一样 直接贴代码了,代码里有详细的注释 代码: ...

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

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

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

    题意:统计区间 [a,b] 中不含 4 和 62 的数字有多少个. 题解:这是数位DP的入门题了,首先要理解数DP的原理,DP[i][j]:代表第i位的第j值,举个栗子:如4715   数位数是从右向 ...

  6. HDU 2089 - 不要62 - [数位DP][入门题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 Time Limit: 1000/1000 MS (Java/Others) Memory Li ...

  7. LightOJ 1140 计数/数位DP 入门

    题意: 给出a,b求区间a,b内写下过多少个零 题解:计数问题一般都会牵扯到数位DP,DP我写的少,这道当作入门了,DFS写法有固定的模板可套用 dp[p][count] 代表在p位 且前面出现过co ...

  8. 51nod 1042 数位dp

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1042 1042 数字0-9的数量 基准时间限制:1 秒 空间限制:131 ...

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

    不要62 题意:给定区间,求在这个区间中有多少个数字,不包含4且不包含62: 这道题作为数位DP的入门题: 暴力也是可以过 #include<cstdio> #include <io ...

随机推荐

  1. JS改变HTML元素的绝对坐标

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DT ...

  2. python创建进程的两种方式

    1.方式1 import time import multiprocessing def task(arg): time.sleep(2) print(arg) def run(): # 进程1 p1 ...

  3. 基本数据类型补充、set集合、深浅拷贝

    一.基本数据类型补充 1,关于int和str在之前的学习中已经介绍了80%以上了,现在再补充一个字符串的基本操作 str.join(可迭代对象): li = ['李嘉诚','何炅','海峰','刘嘉玲 ...

  4. Windows 7 下 Node.js 连接 Oracle

    原创作者: sailtseng 1. 安装 Oracle 11g express  详见: <Windows 7 x64 安装 Oracle 11g Express> 2. 安装 Micr ...

  5. mysql 时间处理函数

    (1)求两个时间戳之间相差的天数 SELECT TIMESTAMPDIFF(DAY,                                              FROM_UNIXTIM ...

  6. linux环境配置时钟同步ntpd服务

    配置: 服务器1:192.168.169.139 服务器2:192.168.169.140 服务器3:192.168.169.141 目的:NTP能与互联网的时间保持同步,而且本身也是一台NTP服务器 ...

  7. 跨平台编译CMake使用

    CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的 ...

  8. curl简介、安装及使用

    目录 curl简介 curl安装 curl使用 curl简介 curl是Linux下一个强大的文件传输工具,它利用URL语法在命令行方式下工作,支持文件上传和下载. curl安装 Ubuntu系统键入 ...

  9. Phpstorm 换行设置(复制 http://jingyan.baidu.com/article/86fae346b2cb673c49121ad3.html)

    很多时候代码太长超出了屏幕的宽度,默认情况下没有自动换行的,我们需要把光标往后挪,才能看到后面代码,显得略为蛋疼,我个人比较喜欢能够自动换行. 下面就说下Phpstorm里如何默认开启自动换行(use ...

  10. Linux 进程管理 进程优先级管理

    Linux进程优先级 Linux 是一个多用户.多任务的操作系统,系统中通常运行着非常多的进程.但是 CPU 在一个时钟周期内只能运算一条指令(现在的 CPU 采用了多线程.多核心技术,所以在一个时钟 ...