PAT A1049 Counting Ones
Sample Input:
12
Sample Output:
5
-
思路 1:当时写的什么玩意…/、
从个位开始,遍历到最高位,计算每位可取1的个数,每位有三种情况,在这三种情况下,从0(now)xx~n这位能取到1的次数分别为:
1)0:
0(1)xxx、1(1)xxx…21(1)xxx…left-1(1)xxx(不能取到(left)(1)xxx超了)每种情况下有(位数*10
)种情况(0(1)000 ~ 0(1)999、1(1)000 ~ 1(1)999…)
2)1:
和0相比,多了一种情况,即当右侧取到left时,多了:(left)(1)000~(left)(1)(right)==n,即多了right + 1
3)>1:和0相比多了(left)(1)000~(left)(1)999,即多了(位数*10
) -
TIPS:记得测试边界数据:1, 230 = 1073741824 = (int)pow(2.0, 30.0);
-
code 1:
#include <stdio.h>
#include <iostream>
using namespace std;
int main(){
int n, cnt = 0;
scanf("%d", &n);
int a = 1, ans = 0;
while(n / a > 0){
int right = n % a;
int left = n / (a * 10);
int now = n / a % 10;
//如果当前位为0:从0—1的过程中,left可以使当前位为1的情况有01xxx-(left-1)1xxx = left种
//每一种都有a(xxx 取 0 ~ (right-1) )个数 => ans += left*a
if(now == 0) ans += left * a;
//当前位为1:使当前位为1的情况多了一种:即left取到left,这种情况不是平凡情况,后考虑
//先不考虑这种情况,即求left0xxx,now=0:ans += left*a
//当左侧取到left时:即变成求left1xxx的个数,为: right + 1(left1000 ~ left1right)(加的1 为left1000)
else if(now == 1) ans += left * a + right + 1;
//最后:当now>1时:left=0~left都能使now为1,且右侧全能取满a个数
else ans += (left + 1) * a;
a *= 10;
}
printf("%d", ans);
return 0;
}
- T4 code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
char s[20];
scanf("%s", s);
int sum = 0;
for(int i = 0; i < strlen(s); ++i)
{
char tmpl[20], tmpr[20];
strncpy(tmpl, s, i); strcat(tmpl, "\0");
strcpy(tmpr, s + i + 1);
int L = atoi(tmpl);
int R = atoi(tmpr);
int numR = pow(10.0, strlen(s) - 1 - i);
if(s[i] > '1')
{
sum += (L + 1) * numR;
}else if(s[i] == '1')
{
sum += (L * numR + R + 1);
}else
{
sum += L * numR;
}
}
printf("%d", sum);
return 0;
}
-
思路2:
[1, 10): 有1个1(1)
[1, 100):有20个1 (1
、11
…91
(10个)+1
0、1
1…1
9(10个))
[1,1000):有300个1 (普通:不考虑百位的1时,每1 ~ 99
有20个1,即[1,100)的情况;特殊:考虑百位的1时多增了100个(1
00~1
99))
…
当枚举到第i位时: [1, 10i ):P i = 10 x P i-1 (普通)+ 10 i-1 (特殊) (递推公式 1-1)
如:
i == 2时
[1, 100): P2 = 10 x P1 + 101 = 10 x 1 + 10 = 20;
i == 3时
[1, 1000):P3 = 10 x P 2 + 10 2 = 10 x 20 + 100 = 300;
… -
求这个递推公式有什么用呢?
任何一个数可以分为2部分:最高位 num[i] +其余低位 num[0 ~ i-1],
1. 若最高位比1大if(num[i] > 1)
:如,212 = 2 + 12 (1、2…199 + 200、201…212),包括:
① 高位产生的1的个数为(以212为例):1、2…199中,即[1,100)中1的个数 + [100,200)中1的个数
- ①-1.不考虑最高位时:[1,100)中1的个数 = P 2 + [100,200)中1的个数 = P2, 即 num[i] * Pi
- ①-2 考虑最高位时:[100,200)中最高位产生100个1,即,10i
② 低位含1个数(上一次递推已经求得):200、201…212中
2. 若最高位等于1if(num[i] == 1)
:如,112 = 1 + 12(1、2…99 + 100、101…112)
① [1,100)有:20个1,即,P2
② [100,112)有:
- ②-1. 最高位1产生的13个1(12-0+1)
- ②-2. 低位含1个数(上一次迭代)
3. 最高位为0:不产生新的1,保持上次迭代的结果
- T2 code: 迭代实现
#include <bits/stdc++.h>
using namespace std;
int Count(int n){
int p = 10, pi = 1, tmp = n / 10;
int cnt = n % 10 > 0 ? 1 : 0;
while(tmp){
int dig = tmp % 10;
if(dig > 1){
cnt = cnt + p + dig * pi;
}else if(dig == 1){
cnt = cnt + pi + (n % p + 1);
}
tmp /= 10;
pi = pi * 10 + p;
p *= 10;
}
return cnt;
}
int main(){
int n;
scanf("%d", &n);
printf("%d", Count(n));
return 0;
}
- T2 code: 数组存储
#include <bits/stdc++.h>
using namespace std;
int Pi[15], P[15], num[15];
void Init(){
P[0] = 1; Pi[0] = 0;
for(int i = 1; i < 11; ++i){
Pi[i] = 10 * Pi[i-1] + P[i-1]; //递推公式 1-1
P[i] = 10 * P[i-1];
}
//Pi = 0, 1, 20, 300, 4000 ....
//P = 1, 10, 100, 1000, 10000 ....
}
int idex = 0;
void toArray(int n){
while(n){
num[idex++] = n % 10;
n /= 10;
}
}
int Count(int n){
toArray(n);
int cnt = num[0] ? 1 : 0;
for(int i = 1; i < idex; ++i){
if(num[i] > 1){
cnt = num[i] * Pi[i] + P[i] + cnt;
// ①-1 ①-2 ②
}else if(num[i] == 1){
cnt = Pi[i] + (n % P[i] + 1) + cnt;
// ① ②-1 ②-2
}
}
return cnt;
}
int main(){
int n;
Init();
scanf("%d", &n);
printf("%d", Count(n));
return 0;
}
T3 code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int para[15];
char s[15];
scanf("%s", s);
para[0] = 0;
for(int i = 1; i < 11; ++i)
{
para[i] = pow(10.0, i-1) + para[i-1] * 10;
}
int len = strlen(s), cnt = 0;
for(int i = 0; i < len; ++i)
{
if(s[i] > '1')
{
cnt += (s[i] - '0') * para[len - 1 - i] + pow(10.0, (len - 1 - i));
}else if(s[i] == '1')
{
char tmp[15];
strcpy(tmp, s + i + 1);
cnt += para[len - 1 - i] + atoi(tmp) + 1;
}
}
printf("%d", cnt);
return 0;
}
//0 1 20 300 4000 50000 600000 7000000 79999999 899999990 1410065307