题目
P1179 [NOIP2010 普及组] 数字统计
题目描述
请统计某个给定范围[L,R]的所有整数中,数字2出现的次数。
比如给定范围[2,22],数字2在数2中出现了1次,在数12中出现1次,在数20中出现1次,在数21中出现>1次,在数22中出现2次,所以数字2在该范围内一共出现了6次。
输入格式
2个正整数L和R,之间用一个空格隔开。
输出格式
数字2出现的次数。
说明/提示
1≤L≤R≤100000
题解
1. 枚举法
只要遍历[ L , R ] [ L , R ] 的每个数的每位数字进行统计就可得到答案,复杂度是O ( n l o g n ) O ( n l o g n ) 。
完整代码
#include <iostream>
using namespace std ;
int main () {
int l,r;
cin >>l>>r;
int cnt = 0 ;
for (int i = l;i<=r;i++){
int tmp = i;
while (tmp){
if (tmp%10 == 2 ) cnt++;
tmp/=10 ;
}
}
cout <<cnt<<endl ;
return 0 ;
}
这个复杂度对于这道题的数据量而言已经够了,但是数据量超过 10 8 10 8 量级后就不可接受了,需要用到公式法。
2.公式法
假设 f ( n , n u m ) f ( n , n u m ) 是从 [ 1 , n ] [ 1 , n ] 所有整数出现数字 n u m n u m 的次数和,那么想要得到 [ L , R ] [ L , R ] 内所有整数出现数字 n u m n u m 的次数和可以通过 f ( r , n u m ) − f ( l − 1 , n u m ) f ( r , n u m ) − f ( l − 1 , n u m ) 得到,其中 0 ≤ n u m ≤ 1 0 ≤ n u m ≤ 1 。
我们可以通过考虑每位数字得到 f ( n , n u m ) f ( n , n u m ) :
1 ≤ n u m ≤ 9 1 ≤ n u m ≤ 9 的情况
假设一个 p p 位正整数 n n 的数位构成情况为 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 n p − 2 ⋯ n 1 n 0 n p − 1 n p − 2 ⋯ n 1 n 0 ¯ ,其中 n i n i 是第 i i 位数的数字 ( 0 ≤ i ≤ p − 1 ) ( 0 ≤ i ≤ p − 1 ) 。
考虑 [ 1 , n ] [ 1 , n ] 中某个数 m m 其 p p 位构成情况为 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 m p − 2 ⋯ m 1 m 0 m p − 1 m p − 2 ⋯ m 1 m 0 ¯ (不够p位数可以补前导0) 。
n i < n u m n i < n u m
若 m m 的 i + 1 i + 1 到 p − 1 p − 1 位的数字构成的新数小于 n n 的 i + 1 i + 1 到 p − 1 p − 1 位的数字构成的新数,即 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 < ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ < n p − 1 ⋯ n i + 1 ¯
那么 m m 可以满足 m i = n u m m i = n u m 且无论第 i − 1 i − 1 位及以后的数字如何也一定在 [ 1 , n ] [ 1 , n ] 中。
当 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 ≥ ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ ≥ n p − 1 ⋯ n i + 1 ¯ 因为 n i < n u m n i < n u m ,如果此时使 m i = n u m m i = n u m ,那么 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 m i > ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 n i m p − 1 ⋯ m i + 1 m i ¯ > n p − 1 ⋯ n i + 1 n i ¯ 则无论 m m 第 i − 1 i − 1 位及以后的数字如何都会 m > n m > n 从而不在 [ 1 , n ] [ 1 , n ] 的范围中。
综上,当 n i < n u m n i < n u m 只有 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 < ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ < n p − 1 ⋯ n i + 1 ¯ 时成立,且此时 [ 1 , n ] [ 1 , n ] 第 i i 位出现 n u m n u m 的次数为 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 × 10 i n p − 1 ⋯ n i + 1 ¯ × 10 i
n i = n u m n i = n u m
当 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 < ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ < n p − 1 ⋯ n i + 1 ¯ 时,次数 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 × 10 i n p − 1 ⋯ n i + 1 ¯ × 10 i 显然成立。
当 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 = ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ = n p − 1 ⋯ n i + 1 ¯ 时,若 m m 满足 m i = n u m m i = n u m ,那么只要 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m i − 1 ⋯ m 0 ≤ ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n i − 1 ⋯ n 0 m i − 1 ⋯ m 0 ¯ ≤ n i − 1 ⋯ n 0 ¯ 即可,此时次数为 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n i − 1 ⋯ n 0 + 1 n i − 1 ⋯ n 0 ¯ + 1 我们约定 i = 0 i = 0 时,¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n i − 1 ⋯ n 0 = 0 n i − 1 ⋯ n 0 ¯ = 0
当 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 > ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ > n p − 1 ⋯ n i + 1 ¯ 那么无论 m m 第 i − 1 i − 1 位及以后的数字如何都会 m > n m > n ,从而不在 [ 1 , n ] [ 1 , n ] 的范围中。
综上,当 n i ≥ n u m n i ≥ n u m 只有 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 ≤ ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ ≤ n p − 1 ⋯ n i + 1 ¯ 时成立,且此时 [ 1 , n ] [ 1 , n ] 第 i i 位出现 n u m n u m 的次数为 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 × 10 i + ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n i − 1 ⋯ n 0 + 1 n p − 1 ⋯ n i + 1 ¯ × 10 i + n i − 1 ⋯ n 0 ¯ + 1
n i > n u m n i > n u m
当 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 < ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ < n p − 1 ⋯ n i + 1 ¯ 时,次数 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 × 10 i n p − 1 ⋯ n i + 1 ¯ × 10 i 显然成立;
当 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 = ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ = n p − 1 ⋯ n i + 1 ¯ 时,因为 n i > n u m n i > n u m ,若使 m i = n u m m i = n u m ,则 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 m i < ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 n i m p − 1 ⋯ m i + 1 m i ¯ < n p − 1 ⋯ n i + 1 n i ¯ 从而无论第 i − 1 i − 1 位及以后的数字如何也一定在 [ 1 , n ] [ 1 , n ] 中,次数为 10 i 10 i 。
当 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 > ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ > n p − 1 ⋯ n i + 1 ¯ 那么无论 m m 第 i i 位及以后的数字如何都会 m > n m > n ,从而不在 [ 1 , n ] [ 1 , n ] 的范围中。
综上,当 n i ≥ n u m n i ≥ n u m 只有 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 ≤ ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 m p − 1 ⋯ m i + 1 ¯ ≤ n p − 1 ⋯ n i + 1 ¯ 时成立,且此时 [ 1 , n ] [ 1 , n ] 第 i i 位出现 n u m n u m 的次数为 ( ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 + 1 ) × 10 i ( n p − 1 ⋯ n i + 1 ¯ + 1 ) × 10 i
n u m = 0 n u m = 0 的情况
这种情况下,我们知道如果某一位是 0 0 ,那么这个整数一定有不为 0 0 的更高位,就需要排除在上一种情况下 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ m p − 1 ⋯ m i + 1 = 0 m p − 1 ⋯ m i + 1 ¯ = 0 的一种可能了。显然在三个可能的 n u m n u m 和 n i n i 关系下,都可能出现这种情况,所以在每次计算完之后需要减去一个关于 ¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯ n p − 1 ⋯ n i + 1 n p − 1 ⋯ n i + 1 ¯ 的所有情况,即减去 10 i 10 i 。
运用以上的结论,每次只需要遍历一次两个端点的位数,是 O ( l o g n ) O ( l o g n ) 的算法。
完整代码
#include <iostream>
#define ll long long
using namespace std ;
ll f (ll n,ll num) {
ll base = 1 ,cnt = 0 ;
while (base<=n){
ll pre = n/(base*10 );
ll suf = n%base;
ll now = n/base%10 ;
if (now<num) cnt+=pre*base;
else if (now == num) cnt+=pre*base + suf + 1 ;
else cnt+=(pre+1 )*base;
if (!num) cnt-=base;
base*=10 ;
}
return cnt;
}
int main () {
std ::ios::sync_with_stdio(0 ),cin .tie(0 ),cout .tie(0 );
ll l,r;
cin >>l>>r;
cout <<f(r,2 )-f(l-1 ,2 )<<endl ;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧