目录
1,题目描述
Sample Input:
12
Sample Output:
5
题目大意
求0-N之间所有的数所含1的全部个数。
2,思路
方法一:纯暴力计算
没错就是你想的那样(结果居然还不错,只有两个点超时,30分拿到22,哈哈哈哈哈哈哈哈)
令i从1到N,求出每一个i中含有1的个数,累加即可。
方法二:找规律
参考柳神的思路(看了好几遍才看懂。。。)
将数据分成三部分:left(now位左边的各位组成的数),now(当前位),right(now位右边的各位组成的数);
now的取值分三种情况讨论(a为right的位数):
1,now==0,ans += left * a:
eg.1230456,left=123,now=0,right=456.。使now位为1的,共有123*1000.
0001xxx,0011xxx,0021xxx,......1221xxx,1231xxx不存在。从000-122共123。而对于0001xxx-1221xxx中任意一个yyy1xxx来说,xxx取值可从000到999共1000。故ans += 123*1000;
2,now==1,ans += left * a + right + 1:
eg.1231456,left=123,now=1,right=456.。使now位为1的,共有123*1000 + 456 + 1.
这时0001xxx,0011xxx,0021xxx,......1221xxx,1231xxx存在。但1231xxx时,并不能直接乘以1000,所以仍是left * a。将1231xxx单独挑出来计算,xxx从000到456(right),共有456+1.。因此ans += 123 * 1000 + 456 + 1.
3,now >= 2,ans += (left + 1)* a:
eg.1233456,left=123,now=3,right=456.。使now位为1的,共有(123 + 1)* 1000.
这时0001xxx,0011xxx,0021xxx,......1221xxx,1231xxx存在,1232xxx,1233xxx。此时1231xxx可以直接乘以1000,所以是(left + 1) * a。
3,代码
方法一
#include<iostream>
#include<algorithm>
using namespace std;
int getNum(int a){
int sum = 0;
while(a > 0){
if(a % 10 == 1)
sum++;
a /= 10;
}
return sum;
}
int main(){
//#ifdef ONLINE_JUDGE
//#else
// freopen("1.txt", "r", stdin);
//#endif
int input;
cin>>input;
int ans = 0;
for(int i = 1; i <= input; i++){
ans += getNum(i);
}
cout<<ans;
return 0;
}
方法二
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
//#ifdef ONLINE_JUDGE
//#else
// freopen("1.txt", "r", stdin);
//#endif
int N;
cin>>N;
int left, right, now, a = 1, ans = 0;
while(N / a){
left = N / (a * 10);
right = N % a;
now = (N / a) % 10;
if(now == 0)
ans += left * a;
else if(now == 1)
ans += (left * a + right + 1);
else
ans += (left + 1) * a;
a *= 10;
}
cout<<ans;
return 0;
}