【1049 30 组合计数】 Counting Ones
传送门
题意
给定 \(n\) 求出从 \(1\sim n\) 中所有数字的所有位上出现的 \(1\) 的个数
数据范围
\(n\leq 2^{30}\)
题解
- 依次考虑每一位上为\(1\)时可能有的数字个数数累计即可
- 利用 \(mid\) 表示当前枚举到的位数,\(l,r\) 分别表示当前位左右两边的数字,\(p\) 用来通过模计算 \(r\) 等的值
- 根据 \(mid\) 当前位上数分成三类
- \(mid=0\),此时只有 \(l\) 为 \(0\sim r\) 的时候有效,数字范围为 \(0\sim l\times p-1\),对答案的贡献为 \(l\times p\)
- \(mid=1\),此时只有左边有 \(1\times p \sim l\times p\) 共 \(l\times p\) 种,右边有\(0\sim r\) 共 \(r+1\)
- \(mid\geq 2\),此时即左边取 \(0\sim l\) 都可, \(p\) 包含右边 \(0\sim p-1\) 共 \(p\) 种情况,贡献为 \((l+1)\times p\)
Code
#include<bits/stdc++.h>
using namespace std;
int main(){
int n; cin>>n;
int l,r,mid;
int ans=0,p=1;
while(n/p){
l=n/(p*10),mid=n/p%10,r=n%p;
if(mid==0) ans+=l*p;
else if(mid==1) ans+=l*p+r+1;
else ans+=(l+1)*p;
p*=10;
}
cout<<ans<<endl;
}

浙公网安备 33010602011771号