1049 Counting Ones(数学逻辑)(化简)

1049 Counting Ones (30 分)

The task is simple: given any positive integer N, you are supposed to count the total number of 1's in the decimal form of the integers from 1 to N. For example, given N being 12, there are five 1's in 1, 10, 11, and 12.

Input Specification:

Each input file contains one test case which gives the positive N (≤2​30​​).

Output Specification:

For each test case, print the number of 1's in one line.

Sample Input:

12

Sample Output:

5

本题题意:

               给定一个十进制数字n, 现在需要求出十进制数 1 - n 中 1这个数字出现的次数,

本题思路:

       1. 首先的思路就是暴力求解, 遍历 1 - n 将每个数的1的个数计算出来,但是这样做会导致超时.

       2.第二种思路 : 是 将 数字 n的 所有 位数 从 低位 到 高位 (eg:一个5位数 就是从个位 到 万位)1的个数分别求出来

          只不过此种思路 需要分3种情况:

         1. 当遍历到的位数值 为 < 1:

             eg: 33330 此时遍历到个位0 , 此时从 1 - n 个位能构成的 1的个数为 3333个 (33330没有1 但是 00001 也算一个1)

           

         2. 当遍历到的位数值 为 =1:

            eg: 33312 此时遍历到10位的0, 此时十位能取到的1的个数为(332 * 10 (*10是因为右边的个位能取到 0 - 9))

                  但是3331x 也是一种情况 , x能取到的范围是 33310 - 33312三种情况

         3.  当遍历到的位数值 为 >1:

           eg: 33312 此时遍历到百位的3, 此时百位能取到的1的个数为(333 * 100 (因为百位的3 > 1因此不要作特殊处理))

 

暴力超时代码:

#include<iostream>
using namespace std;
int main(){
	int n, count = 0;
	scanf("%d", &n);
	for(int i = 1; i <= n; i++){
		int temp = i;
		while(temp != 0){
			if(temp % 10 == 1){
				count++;
				temp = temp / 10;	
			}else
				temp = temp / 10;
		}
	}
	printf("%d\n", count);
	return 0;
} 

改进代码:

#include<iostream>
using namespace std;
int main(){
	int n, now, left, right, a = 1, ans = 0;
	scanf("%d", &n);
	while(n / a != 0){
		left = n / (a * 10);
		now  = n / a % 10;
		right = n % a;
		if(now == 0)
			ans += left * a;
		else if(now == 1)
			ans += left * a + 1 + right;
		else if(now > 1)
			ans += (left + 1) * a;
		a *= 10;
	}
	printf("%d\n", ans);
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值