您的位置:首页 > 其它

PAT 1049. Counting Ones

2014-08-20 21:24 281 查看
分析起来太心塞了!!

我本来是这么想的,比方说给的一个数是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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: