题目描述
The task is simple: given any positive integer N, you aresupposed to count the total number of 1's in the decimal form of the integersfrom 1 to N. For example, given N being12, there are five 1's in 1, 10, 11, and 12.
输入描述:
Each input file contains one test case which gives the positiveN (<=230).
输出描述:
For each test case, print the number of 1's in one line.
输入例子:
12
输出例子:
5
这题虽然题面看起来很简单,但是,技巧性特别强,
首先遍历1到n所有的数肯定超时,
后来我考虑将a1a2a3a4类似这样的数划分为a1000 a200 a30 a4,这四个区间,然后分别求这四个区间里面的1的个数,这样虽然时间快,但是代码太复杂了,且容易出错
后来我又想,对于a1a2a3a4而言,a3位置上的1的个数不是只和a1a2,a4这两个数有关吗,比如1234,十位上的1的个数就为(12+1)*(10),因此就能够得到规律
把数拆分为left,mid,right三部分,
当mid>1的时候,mid位置上的1的个数为(left+1)*(10^len(right))
当mid ==1 的时候,为(left)*(10^len(right))+right+ 1
当mid == 0 的时候,为(left)*(10^len(right))
Len(right)为right这个数的长度
使用stringstream来实现int和string的转换
Stringstream ss;
Ss<<int;
ss>>string;
或者是
Stringstream ss;
Ss<< string;
ss>>int;
当编译器不支持long long类型的时候,需要使用_int64类型,当时交上去的代码需要使用long long类型
输出long long 类型需要printf(“%lld”,a)需要stdio.h头文件
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int N;
string Ntmp;
__int64 theOneCount=0;
int leftNum,midNum,rightNum;
cin>>N;
stringstream ss;
ss << N;
ss >> Ntmp;
for(int i=0;i<(int)Ntmp.size();i++)
{
leftNum = atoi(Ntmp.substr(0,i-0).c_str());
midNum = Ntmp[i]-'0';
rightNum = atoi(Ntmp.substr(i+1,Ntmp.size()-(i+1)).c_str());
if(midNum>1)
{
theOneCount+=pow(10,Ntmp.size()- (i+1))*(leftNum+1);
}
else if(midNum == 1)
{
theOneCount+=(pow(10,Ntmp.size()- (i+1)))*(leftNum) + rightNum + 1;
}
else
{
theOneCount+=(pow(10,Ntmp.size()- (i+1)))*(leftNum);
}
}
printf("%lld", theOneCount);
return 0;
}