题目地址:
https://www.luogu.com.cn/problem/P1591
题目描述:
求
n
!
n!
n!中某个数码出现的次数。
输入格式:
第一行为
t
(
t
≤
10
)
t(t \leq 10)
t(t≤10),表示数据组数。接下来
t
t
t行,每行一个正整数
n
(
n
≤
1000
)
n(n \leq 1000)
n(n≤1000)和数码
a
a
a。
输出格式:
对于每组数据,输出一个整数,表示
n
!
n!
n!中
a
a
a出现的次数。
先用高精度乘以单精度的方式预处理出 1 ∼ 1000 1\sim 1000 1∼1000的每个数的阶乘,应答询问的时候只需要找到对应的数遍历每个数字即可。数字的长度约等于 log 10 1000 ! = ∑ k = 1 1000 log 10 k < 3000 \log_{10}1000!=\sum_{k=1}^{1000} \log_{10}k<3000 log101000!=∑k=11000log10k<3000。代码如下:
#include <iostream>
using namespace std;
const int N = 3003;
int a[1005][N];
void init() {
a[1][0] = a[1][1] = 1;
for (int i = 2; i <= 1000; i++) {
a[i][0] = 1;
int t = 0, j;
for (j = 1; j <= a[i - 1][0]; j++) {
a[i][j] = a[i - 1][j] * i + t;
t = a[i][j] / 10;
a[i][j] %= 10;
}
while (t) {
a[i][j] = t % 10;
t /= 10;
j++;
}
a[i][0] = j - 1;
}
}
int main() {
init();
int T;
scanf("%d", &T);
while (T--) {
int n, k;
scanf("%d%d", &n, &k);
int res = 0;
for (int i = 1; i <= a[n][0]; i++)
if (a[n][i] == k) res++;
printf("%d\n", res);
}
}
预处理时间复杂度 O ( n log 1000 ! ) O(n\log 1000!) O(nlog1000!),每次询问时间 O ( 1 ) O(1) O(1),空间 O ( n log 1000 ! ) O(n\log 1000!) O(nlog1000!)。