51nod 1009 数位dp入门
2017-08-20 15:33
295 查看
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1009
基准时间限制: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示例
12Output示例
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[15][10]; int bit[15]; int p10[10]={1}; int cal(int N){ int ans=0,len=0,ok=0; while(N){ bit[len++]=N%10; N/=10; } bit[len]=-1; for(int i=len-1;i>=0;--i){ for(int k=0;k<bit[i];++k){ ans+=f[i+1][k]; int tot=0; for(int j=i+1;j<len;j++){ if(bit[j]==1){ tot++; } } ans+=tot*p10[i]; } } return ans; } int main(){ int i,j,k; for(i=1;i<10;++i) p10[i]=p10[i-1]*10; f[1][1]=1; for(i=2;i<=10;++i){ for(j=0;j<10;++j){ for(k=0;k<10;++k){ f[i][j]+=f[i-1][k]; } if(j==1) f[i][j]+=p10[i-1]; } } int N; while(scanf("%d",&N)==1) printf("%d\n",cal(N+1)); return 0; }
f[i]表示所有的i位数中包含1的个数,有前导零的数也计算在内,因为在计算高位时低位可以为零。
#include<bits/stdc++.h> using namespace std; #define LL long long LL f[15]={0,1}; LL p10[15]={1,1}; int bit[15]; void init(){ for(int i=1;i<=10;++i) p10[i]=p10[i-1]*10; for(int i=2;i<=10;++i) f[i]=f[i-1]*10+p10[i-1]; } LL cal(int N){ int len=0; while(N){ bit[len++]=N%10; N/=10; } bit[len]=-1; LL ans=0,one=0; for(int i=len-1;i>=0;--i){ ans+=f[i]*bit[i]; if(bit[i]>1) ans+=p10[i]; ans+=p10[i]*bit[i]*one; if(bit[i]==1) one++; } return ans; } int main(){ int n,i,j,k; init(); while(scanf("%d",&n)==1){ printf("%lld\n",cal(n+1)); } return 0; }
相关文章推荐
- 【数位dp入门】51nod 1009 数字1的数量
- 51Nod 1009 数字1的数量(数位dp)
- 51nod 1009 数字1的数量(数位dp)
- 51Nod - 1009 数位dp
- 51nod 1009 数字1的数量 数位dp
- 51nod 1009 数字1的数量(数位dp)
- 51Nod 1009 1042 数位DP
- 【51nod 1009】数字1的数量 【数位DP 模板】
- 51nod 1009 数字1的数量(数位dp)
- 51nod-1009-数位dp
- 51nod 1009 数字1的数量【数位dp】
- 51Nod 1009 数字1的个数 | 数位DP
- 数位DP入门之hdu 3652 B-number
- 【51Nod】1042 - 数字0-9的数量(数位dp & 递归)
- hdu2089不要62 (数位dp入门题)
- 51nod 1042 数字0-9的数量(数位DP)
- hdoj 2089 不要62(数位dp入门模板)
- HDU 2089 不要62(数位DP入门+模板)
- 51nod 1043 数位dp
- HDU3555:Bomb(数位dp入门)