P1591 阶乘数码

P1591 阶乘数码

  • 考点:高精度 * 低精度

  • 测评链接:P1015

  • 讲评视频:稍后上传

分析&题意

​ 这道题要求的是在给定的阶乘 n ! n! n! 中,某个特定数码(比如 0 , 1 , 2 , . . . , 9 0, 1, 2, ..., 9 0,1,2,...,9 )出现的次数。阶乘 n ! n! n! 是从 1 1 1 乘到 n n n 的所有整数的乘积,即 n ! = 1 ∗ 2   ∗ . . .   ∗ n − 1 ∗ n n!=1 * 2 \ * ... \ * n-1 * n n!=12 ... n1n

例子解释

以样例输入为例:

  1. 第一组数据: n = 5 n=5 n=5,数码 a = 2 a=2 a=2
    • 5 ! = 1 × 2 × 3 × 4 × 5 = 120 5!=1×2×3×4×5=120 5!=1×2×3×4×5=120
    • 120 120 120 中,数码 2 2 2 出现了 1 1 1 次。
    • 因此,输出是 1
  2. 第二组数据: n = 7 n=7 n=7,数码 a = 0 a=0 a=0
    • 7 ! = 1 × 2 × 3 × 4 × 5 × 6 × 7 = 5040 7!=1×2×3×4×5×6×7=5040 7!=1×2×3×4×5×6×7=5040
    • 5040 5040 5040 中,数码 0 0 0 出现了 2 2 2 次。
    • 因此,输出是 2
  • 本题本质上就是高精度( 阶乘 ) * 低精度 ( 1 ∼ n 1 \sim n 1n),注意细节即可, a n s [ 1 ] = 1 ans[1] = 1 ans[1]=1 表示为 1 1 1 的阶乘初始化为 1 1 1

代码

#include<bits/stdc++.h>
using namespace std;

#define ll long long
const int N = 5000;
int T, n, target;
int ans[N];

// 高乘以低
int fact( int n, int a[] ) {
	int lenc = 1; // 进位
	for (int i = 1, j, x; i <= n; i++) { // j 有效位数, x 进位
		// 高精度 * 低精度,进位初始化为 0
		x = 0;
		for (j = 1; j <= lenc; j++) { // 乘积
			a[j] = (a[j] * i) + x; // 被乘数[j] * 乘数 i + 进位
			x = a[j] / 10; // 处理进位
			a[j] %= 10; // 保留个位
		}
		while ( x > 0 ) //最高位进位
		{
			a[j++] = x % 10;
			x /= 10;
		}
		lenc = j-1; // j 后退一位指向最高位有效位
	}
	return lenc; //实际有效位
}

ll count( int a[], int len, int t ) {
	ll cnt = 0;
	for (int i = len; i >= 1 ; i--) // 统计有效数码
		if ( a[i] == t )
			cnt++;
	return cnt;
}

int main() {
	cin >> T;
	while ( T-- ) {
		cin >> n >> target;
		memset( ans, 0, sizeof ans );
		ans[1] = 1; // 1 的阶乘为 1,否则
		// 求阶乘,存放到 ans 数组中,返回长度
		int len = fact( n, ans );
		// 统计数码 target 出现的次数
		cout << count( ans, len, target) << endl;
	}
}
  • 20
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值