Leading 1s
题目链接:ARC 127A
题目大意
给你一个函数 f(x) 定义为它十进制的前导 1 个数。
然后要你求 f(1)+f(2)+…+f(x)。
思路
考虑数位 DP,计算每一位能贡献多少次。
然后就是贴着上界,如果上界大于
1
1
1,后面就任选都能贡献到,而且后面也是任选。
如果上界是
1
1
1,那后面能选的都能贡献到,然后后面就继续贴着。
如果上界是
0
0
0,那后面选啥都没有,直接退出。
代码
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll n, ans, ten[31];
ll w, a[31];
void work(ll now, ll t) {
if (now > t) return ;
if (t != w) {
ans += ten[t - now];
work(now + 1, t);
return ;
}
else {
if (a[t - now + 1] > 1) {//这里上界是 1 以上你选了 1,后面就随便选
ans += ten[t - now];
work(now + 2, t + 1);
}
else if (a[t - now + 1] == 0) return ;//这里上界是 0,不会有贡献
else {
ans += n % ten[t - now] + 1ll;//算这一位是 1 的贡献,然后继续
work(now + 1, t);
}
}
}
int main() {
ten[0] = 1;
for (int i = 1; i <= 16; i++)
ten[i] = ten[i - 1] * 10;
scanf("%lld", &n);
ll nn = n;
while (nn) {
w++; a[w] = nn % 10;
nn /= 10;
}
for (int i = 1; i <= w; i++) {
work(1, i);
}
printf("%lld", ans);
return 0;
}