题目
题目描述
求 n! 中某个数码出现的次数。
输入格式
第一行为t(t≤10),表示数据组数。接下来t 行,每行一个正整数n(n≤1000) 和数码a。
输出格式
对于每组数据,输出一个整数,表示 n! 中 a 出现的次数。
示例
输入
2
5 2
7 0
输出
1(5! = 120,2出现一次)
2(7! = 5040,0出现2次)
解题思路
这道题放在模拟和高精度的官方题单中,可以说是明示该题的解题关键在于高精度乘积计算。
由n≤1000我们可知,当n取到最大值时,长度也不会超过,即3000。
保险起见,我们把数组直接开到5000。
通过将每一位的数分别存储在数组一个位置上,进行乘法计算时,只需将每一位的数对其进行乘法处理,最后做进位处理就完成了高精度乘法的运算。
之后通过遍历运算结果,与对应的a的数码进行匹配,计算出其出现的次数,进行输出,完成。
高精度乘法运算
先上代码...
//外层循环数组数
for (int i = 0; i < t; i++)
{
//清空number数组
for (int k = 0; k < 5000; k++)
number[k] = 0;
number[0] = 1; //初始化number[0] = 1用于进行第一次计算
length = 1; //用于记录结果的长度
int l = 0;
//进行阶乘
for (int k = 1; k <= n[i]; k++)
{
//把每一位做乘法
for (l = 0; l < length; l++)
number[l] = number[l] * k;
//把每一位做进位
for (l = 0; l < length; l++)
{
number[l + 1] += number[l] / 10;
number[l] = number[l] % 10;
}
if (length < l + 1 && number[l] != 0)
length = l + 1;
//对最后一位做最后的处理
while (number[l] >= 10)
{
number[l + 1] += number[l] / 10;
number[l] = number[l] % 10;
l++;
length++;
}
}
这边的乘法为每一个位置上的值都进行乘积处理后,再统一进行进位处理。
看上述代码也可以发现,我的进位是通过将所有的每一位的值都往最后一位堆积,最后循环处理最后一位数就可以完成整体的进位,并实现对结果的长度的更新。
AC代码
#include<iostream>
#include<string>
using namespace std;
int number[5000] = { 0 };
int main()
{
int t = 0; //数组数
int length = 0; //长度
int n[11] = { 0 }; //n的值
int a[11] = { 0 }; //a的值
//输入数组数
cin >> t;
//输入每个数组的值
for (int i = 0; i < t; i++)
{
cin >> n[i] >> a[i];
}
//外层循环数组数
for (int i = 0; i < t; i++)
{
//a的数
int count = 0;
//清空number数组
for (int k = 0; k < 5000; k++)
number[k] = 0;
number[0] = 1;
length = 1;
int l = 0;
//进行阶乘
for (int k = 1; k <= n[i]; k++)
{
//把每一位做乘法
for (l = 0; l < length; l++)
{
number[l] = number[l] * k;
}
//把每一位做进位
for (l = 0; l < length; l++)
{
number[l + 1] += number[l] / 10;
number[l] = number[l] % 10;
}
if (length < l + 1 && number[l] != 0)
length = l + 1;
//对最后一位做最后的处理
while (number[l] >= 10)
{
number[l + 1] += number[l] / 10;
number[l] = number[l] % 10;
l++;
length++;
}
}
//循环结果数组,匹配对应的a值
for (int k = 0; k < length; k++)
{
if (number[k] == a[i])
count++;
}
cout << count << endl;
}
return 0;
}