PAT 1049. Counting Ones

分析起来太心塞了!!

我本来是这么想的,比方说给的一个数是4165,我先算0——9999含有多少1,这个是好算的。再算1000——1999有多少个1,这个也好算,比0——9999多了一千个1,然后算2000——2999,也一样。

然后算4000——4099,再算4100——4159,再算4160——4165。

后来想想细节很麻烦啊,因为这不只是“先算高位再算低位”,像4165,它百位上是1,这会影响到4160——4165之间1的个数的。


所以我后来这么算,我先算这个数,比方说就是4165,它个位上出现过多少次1?

4165/10=416,所以个位上经历过416轮的变化,每轮都有一次1出现,所以有416个1,最后还有个半轮,个位从0变到5,这半轮里也出现过一个1,所以个位上总共出现过417个1。

然后算十位上,4165/100=41,十位上经历过41轮的变化,每轮都有十次1出现,所以有410个1,最后还有半轮,从0X变到6X,这段变化里,十位上也出现过十个1,所以十位上总共出现过420个1。

然后算百位上,4165/1000=4,百位上经历过4轮变化,每轮都有一百次1出现,所以有400个1,重点来了,百位上是1,4100——4165这一段儿,百位上出现的1的个数是66个,所以百位上总共出现过466个1。

千位,4165/10000=0,千位没有经历过整轮的变化,但是还是有半轮的,这半轮里,千位从0变到4,出现过100个1。

总计417+420+466+100。

写代码的时候,具体的实现也还是很烦很烦很烦啊,要有耐性。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
int n;
char shu[11];
int len;
void trans(){
	int temp=n;
	int i;
	len=0;
	while(temp>0){
		shu[len++]=temp%10;
		temp/=10;
	}
	for(i=0;i<len/2;i++){
		temp=shu[i];
		shu[i]=shu[len-1-i];
		shu[len-1-i]=temp;
	}
}
int main(){
	int i;
	double ans;
	int div,result,after,add;
	while(~scanf("%d",&n)){
		trans();
		ans=0;
		i=1;
		while(i<=len){
			div=((int)pow(10,i));
			add=((int)pow(10,i-1));
			result=n/div;
			after=shu[len-i];
			ans+=result*add;
			if(after>1){
				ans+=add;
			}
			else if(after==1){
				ans+=(n%add+1);
			}
			i++;
		}
		printf("%.0lf\n",ans);
	}
return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值