预处理到最大 n 的阶乘,用 Python 大整数转字符串后统计指定数字出现次数。
OJ: luogu
题目 ID: P1591
难度:入门
标签:高精度字符串python
日期: 2026-07-15 22:10
题意
多组询问,每组给出 n 和一个数码 a,求 n! 的十进制表示中 a 出现了多少次。
思路
n <= 1000,Python 的大整数可以直接保存 1000!。为了避免每组询问都重新算阶乘,先找到所有询问中的最大 n,预处理:
python
factorials[i] = factorials[i-1] * i回答时把 factorials[n] 转成字符串,用 count(digit) 统计。
这题是 Python 大整数和字符串统计练习,不创建 brute.py。
Python 知识
/home/rainboy/mycode/hugo-blog/content/program_language/python/math_tools.md:Pythonint支持任意精度整数。/home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md:多组输入可以用sys.stdin.read().split()统一读取。str(big_number).count(digit)可以统计字符出现次数。
代码
python
import sys
data = sys.stdin.read().split()
test_count = int(data[0])
queries = []
max_n = 0
index = 1
for _ in range(test_count):
n = int(data[index])
digit = data[index + 1]
queries.append((n, digit))
max_n = max(max_n, n)
index += 2
factorials = [1] * (max_n + 1)
for number in range(1, max_n + 1):
factorials[number] = factorials[number - 1] * number
answers = []
for n, digit in queries:
answers.append(str(str(factorials[n]).count(digit)))
print("\n".join(answers))cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-27 00:00
* update_at: 2026-07-27 00:00
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXLEN = 3000; // 1000! 大约 2568 位
// 大整数乘法:a[0..len_a-1] *= b,b 是一个小整数
// a 是逆序存储的数组,低位在前
int mul_int(int *a, int len_a, int b) {
int carry = 0;
for (int i = 0; i < len_a; i++) {
int prod = a[i] * b + carry;
a[i] = prod % 10;
carry = prod / 10;
}
while (carry) {
a[len_a++] = carry % 10;
carry /= 10;
}
return len_a;
}
// 统计大整数 a[0..len-1] 中数码 digit 出现的次数
int count_digit(int *a, int len, int digit) {
int cnt = 0;
for (int i = 0; i < len; i++) {
if (a[i] == digit) cnt++;
}
return cnt;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n, digit;
cin >> n >> digit;
int fact[MAXLEN] = {0};
fact[0] = 1; // 0! = 1
int len = 1;
// 计算 n!
for (int i = 2; i <= n; i++) {
len = mul_int(fact, len, i);
}
cout << count_digit(fact, len, digit) << "\n";
}
return 0;
}复杂度
预处理到最大 n 需要做 max_n 次大整数乘法。每组询问需要把对应阶乘转字符串并统计,复杂度与数字位数有关。
总结
Python 处理高精度阶乘题很直接:先用大整数算出结果,再把十进制表示当字符串处理。