51nod 1009 数字1的数量
基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题
给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数。
例如:n = 12,包含了5个1。1,10,12共包含3个1,11包含2个1,总共5个1。
Input
输入N(1 <= N <= 10^9)
Output
输出包含1的个数
Input示例
12
Output示例
5
题意:中文
思路:数位dp的应用
#include <iostream>
#include <cmath>
#include <cstring>
//#pragma warning(disable:4996)
using namespace std;
typedef long long ll;
ll s;
ll dp[20]; // 前x位中1出现次数(0~9均是如此)
void init()
{
memset(dp, 0, sizeof(dp));
int i;
for (i = 1; i <= 9; i++)
{
dp[i] = dp[i - 1] * 10 + pow(10, i - 1); // 前x-1位出现1次数*10 + 第x位为1的情况数
}
}
ll count(ll x)
{
ll result = 0;
ll len = 0;
ll digit = 0;
ll radix = 1;
ll tail = 0;
while (x != 0)
{
digit = x % 10;
x = x / 10;
++len;
if (digit > 1)
{ // radix就代表10的多少多少次方
result += radix + digit * dp[len - 1]; // ex:241 result(200~241) += radix(百位为1)+ digit
} // * dp[len - 1](0~199除去百位为1)
else if (digit == 1)
{ // +1是代表取的那个整数
result += tail + 1 + dp[len - 1]; // ex:141 result(100~141除去百位的1) += tail(101~141百位
} // 为1) + 1(100的百位为1) + dp[len - 1](0~99)
tail = tail + digit * radix; // 头为1个数
radix *= 10; // 倍率
}
return result;
}
int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout);
init();
cin >> s;
cout << count(s)<<endl;
return 0;
}