题目大意
给定一个区间[a,b],统计区间内0,1,2,3,4,5,6,7,8,9各个数字出现的个数。
解题思路
问题转化为(0,n】区间各个数字出现的个数(最后用b减去a-1就是结果),关键是怎样去计数呢?
举个例子大家就会非常明白,以2345为例,分区间
————
0 0 0 1
…
1 0 0 0
…
2 0 0 0
————
2 0 0 1
…
2 3 0 0
————
2 3 0 1
…
2 3 4 0
————
2 3 4 1
…
2 3 4 5
————
第一个区间,先取得最高位2,高位上的0,1出现的次数为1000次,而2出现的次数是000~345,即346次;再看低位000~999,0~9出现的次数是相同的3*1000/10,高位0,1决定最终结果×2,即0~9次数加上2×3×1000/10;
注意这一步多考虑了前导零,而且只有在这一步,接下来的区间内并不会出现前导零,所以可以先不用管,等把所有区间都解决了,最后再减去前导零。
接下来分析第二个区间2001~2300.同样地,先取得最高位3(此时2的所有情况在第一个区间已经计数完毕,最高位已经失去意义),从001~300,高位上0,1,2出现的次数是100次,(0不是前导零啦!),低位00~99中0~9各出现3×2×100/10,分别计数;
以此类推至第3、4区间2301~2340,2341~2345,循环处理相同。
最后,不要忘记把多算的前导零减去,千位上的0多算了1000次,百位100,视为10,个位1,即最后减去1000+100+10+1
参考代码+部分解释
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 7e4+10;
int a,b,f[10]={0},g[10]={0};
void swap(int &a,int &b){int temp=a;a=b;b=temp;return;}
void solve(int n,int *h)//计算(0,n]区间0123456789出现的次数,记录在数组f[]中,以2345为例
{
if(n==0) return;
int m=n,len=0;while(n){len++;n/=10;};n=m; //得到长度len,用m恢复n
for(int i=len;i>0;i--){ //从高位向低位一个一个处理
int temp=(int)pow(10.0,i-1),digit=n/temp; //取高位digit //处理高位
for(int j=0;j1;
int res=digit*(i-1)*temp/10;for(int i=0;i<10;i++) h[i]+=res;
n%=temp;
}
for(int i=len;i>0;i--) h[0]-=(int)pow(10.0,i-1);//对多余0的处理
return;
}
int main()
{
// freopen("input.txt","r",stdin);
while(cin>>a>>b&&a+b){
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
if(a>b) swap(a,b);
solve(a-1,f);
solve(b,g);
for(int i=0;i<10;i++)
if(i) cout<<" "<else cout<cout<return 0;
}
题目大意
统计区间[a,b]中数字0出现的个数
解题思路
是poj2282的一部分,解题思路是一样的,但是发现了poj2282算法中的一出问题(浮点数精度误差),强制转换double为int会有误差的,比如temp=100,实际会生成99,所以在这里我重新定义了一个变量x记录1000->100->10->1,避免了浮点数误差问题。
还要要注意的是开始区间m=0的问题,m-1是-1,求出来的结果与实际不符,所以我还是特判了一下m=0的情况,从1开始的仍然按照上一道题的处理方法解决。
参考代码
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 7e4+10;
ll m,n;
ll solve(ll n)//计算(0,n]区间0出现的次数,记录在ans中
{
ll ans=0;
ll m=n,len=0,x=1;while(n){len++;n/=10;x*=10;};n=m; //得到长度len,用m恢复n
for(ll i=len;i>0;i--){ //从高位向低位一个一个处理
x/=10;int temp=x,digit=n/temp; //取高位digit //处理高位
if(digit>0) ans+=temp;else ans+=n%temp+1;
ll res=digit*(i-1)*temp/10;ans+=res;
n%=temp;
}
x=1;
for(int i=0;i10;}//对多余0的处理
return ans;
}
int main()
{
// freopen("input.txt","r",stdin);
while(cin>>m>>n&&(m>=0)){
if(m==0) cout<1<else cout<1)<return 0;
}