51nod 1009 数位dp入门

Posted zzq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

 









以上是关于51nod 1009 数位dp入门的主要内容,如果未能解决你的问题,请参考以下文章

51 Nod 1009 数字1的数量(数位dp)

51Nod 1009 数字1的个数 | 数位DP

51nod 1009 数字1的数量 数位dp

51nod 1009 - 数字1的数量 - [数位DP][模板的应用以及解释]

51Nod1009

51nod1009 数字1的数量