您的位置:首页 > 其它

51nod-1042 数字0-9的数量

2018-03-12 17:11 330 查看
1042 数字0-9的数量 

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

 收藏

 关注给出一段区间a-b,统计这个区间内0-9出现的次数。比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次。Input
两个数a,b(1 <= a <= b <= 10^18)
Output
输出共10行,分别是0-9出现的次数
Input示例
10 19
Output示例
1
11
1
1
1
1
1
1
1
1
思路:两种求解方法
方法一:求当前数位上出现 目标数p的次数 sum 。设当前数位上的数为 x;有三种情况:
1.x>p   则sum 受到当前位以及高位的影响。 
2.x==p 则sum 受到低位以及高位的影响
3.x<p   则sum 受到高位的影响

方法二:求1到 由低位到当前数位所组成的数 出现 p的次数。同样有三种情况:

1.x>p   则sum 受到当前位及低位的影响
2.x==p 则sum 受到低位的影响
3.x<p   则sum 受到低位的影响

code1:#include<iostream>
using namespace std;
typedef long long LL;

LL f(LL n,int p);
int main()
{
ios::sync_with_stdio(false);
LL a,b;
while(cin>>a>>b){ //由低位到高位分析
for(int i=0;i<=9;++i)
cout<<f(b,i)-f(a-1,i)<<endl;
}
return 0;
}

LL f(LL n,int p)
{
LL lower=0,curr=0,higher=0;
LL d=1,ans=0;
while(n/d!=0){
lower=n-(n/d)*d;
curr=(n/d)%10;
higher=n/(d*10);
if(curr<p){
ans+=higher*d;
}else if(curr==p){
if(p) ans+=higher*d+lower+1;
else ans+=(higher-1)*d+lower+1;
}else{
if(p) ans+=(higher+1)*d;
else ans+=higher*d;
}
d*=10;
}
return ans;
}

code2:#include<iostream>
using namespace std;
typedef long long LL;

LL dp[20];
LL a,b;

LL solve(int p,LL n);
int main()
{
ios::sync_with_stdio(false);
LL t=1;
for(int i=1;i<20;t*=10,++i)
dp[i]=dp[i-1]*10+t;
while(cin>>a>>b){
for(int i=0;i<10;++i)
cout<<solve(i,b)-solve(i,a-1)<<endl; 
}
return 0;
}

LL solve(int p,LL n)
{
LL ans=0,tail=0,radix=1,m=n;
for(int k=1;n;++k){
LL digit=n%10;
n/=10;
if(digit>p){
ans+=digit*dp[k-1]+radix;
}else if(digit==p){
ans+=digit*dp[k-1]+tail+1;
}else{
ans+=digit*dp[k-1];
}
tail+=digit*radix;
radix*=10;
}
if(!p){ //若为0,则需去除多求的0, 如 0,01 
for(LL radix=1;m;radix*=10,m/=10)
ans-=radix;
}
return ans;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: