统计次数【清华大学考研机试题】

统计次数

给定两个正整数 \(n\)\(k\),求从 \(1\)\(n\)\(n\) 个正整数的十进制表示中 \(k\) 出现的次数。

输入格式
共一行,包含两个整数 \(n\)\(k\)

输出格式
输出一个整数,表示答案。

数据范围
\(1≤n≤10^6,\)
\(1≤k≤9\)
输入样例:
12 1
输出样例:
5
样例解释
\(1\)\(12\) 这些整数中包含 \(1\) 的数字有 \(1,10,11,12,\)一共出现了 \(5\)\(1\)

暴力 \(O(nlogn)\)(174 ms)

具体实现
从 1 遍历到 n,分别统计每个数中 k 出现的次数。
不断取 x 的末尾,判断它是否为 k,再把 x 除以 10(舍弃末位)。

点击查看代码
#include<iostream>

using namespace std;
typedef long long LL;
int n,k;
LL ans;

int main(){
	cin >> n >> k;
	for(int i = 1; i <= n; i ++ ){
		int t = i;
		while(t){
			if(t % 10 == k)ans ++;
			t /= 10;
		}
	}
	cout << ans;
}

数位DP \(O(n)\)(62 ms)

\(f[i]\) 表示 \(i\) 中含有几个 \(k\)。观察可得到转移方程 \(fi=f⌊i/10⌋+ (i \% 10 == k)\),其中 \(bj\)\(j\) 是否等于 \(k(0≤j≤9)\)。如此递推即可

点击查看代码
#include<iostream>
#include<algorithm>

using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int n,k;
int f[N];
LL ans;

int main(){
	cin >> n >> k;
	for(int i = 1; i <= n; i ++ )f[i] = f[i / 10] +  (i % 10 == k),ans += f[i];
	cout << ans;
}
posted @ 2023-01-05 22:09  Keith-  阅读(22)  评论(0编辑  收藏  举报