【PAT甲级】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

思路:解题思路

结论:

  1. 每个位上出现1的次数与before有关,且至少有before*pow(10,w)个,这里w是after的位数。例如222,三位数,求的是十位上的数字为1的数字出现的次数,百位跟十位已经确定了有三种情况,这里after为1位数,即可以从0变化到9即有10种可能,例如百位+十位为01,则有010 011 … 019这十种可能。

  2. 每个位上出现1的次数还与该位上的数字d有关,如果d>1,则上述总结1还要加一种可能,即有(before+1)*pow(10,w)个。例如222:即如果202,至少可取01 11,例如222 d=2>1,还可以取21,且也可以把21后面的取完。

  3. 每个位上出现1的次数还与该位上的数字d有关,如果d=1,则有before*pow(10,w)+(after+1)个。例如222,212,202,百位+十位至少都可以取01 11,然后对于d=1,即212,还可以取210 211 212这三种情况。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <cmath>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define mem(a,n) memset(a,n,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const ll INF=0x3f3f3f3f;
const int N = 2e3+5;

int main() {
    int n;
    cin>>n;
    int after=0,w=0,sum=0;
    while(n>0) {
        ///求出每个位置的before, d, after
        int before=n/10;
        int d=n%10;
        ///d>1时
        sum+=(before+((d>1)?1:0))*pow(10,w);
        ///d==1时
        if(d==1) sum+=after+1;
        ///更新下一轮的after和w
        after=d*pow(10,w)+after;
        w++,n/=10;
    }
    cout<<sum<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/feng_zhiyu/article/details/81348452