码迷,mamicode.com
首页 > 其他好文 > 详细

51nod 1009 数位dp入门

时间:2017-08-20 17:02:25      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:输出   示例   return   十进制   black   整数   com   一段   inpu   

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 }

 

51nod 1009 数位dp入门

标签:输出   示例   return   十进制   black   整数   com   一段   inpu   

原文地址:http://www.cnblogs.com/zzqc/p/7400211.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!