SCU - 2763 Factorial(任意阶乘中任意数的次数)

题目:

Description

Robby is a clever boy, he can do multiplication very quickly, even in base-2 (binary system), base-16 (hexadecimal system) or base-100000. Now he wants to challenge your computer, the task is quite simple: Given a positive integer N, if we express the N ! (N ! = N * (N - 1) * (N - 2) * ... * 2 * 1) in base-B, how many ZEROs there will be at the end of the number. Can you make a wonderful program to beat him?

Input

Each test case contain one line with two numbers N and B. (1 ≤ N ≤ 10^9, 2 ≤ B ≤ 100000) The input is terminated with N = B = 0.

Output

Output one line for each test case, indicating the number of ZEROs.

Sample Input

7 10 7 10000 7 2 0 0

Sample Output

1 0 4


题目的意思就是,任给2个整数n、b,要求n!的b进制表示中有多少个后缀0

即求满足b^k整除n!的最大整数k

如果b是素数的话就非常简单,如果你不这么认为的话,请点击打开我的博客

我的这篇博客是另外1个题目,和这个有关系,下面这个重要的函数我又用了一次

long long degree_in_fact(long long m, int p)
{
	if (m)return degree_in_fact(m / p, p) + m / p;
	return 0;
}

本题b不是素数,但是原理的本质却是一样的。

把b进行唯一分解(不知道的请点击打开链接(算数基本定理))

比如b=224=2^5 * 7

那么b^k|n等价于2^(5*k)|n且7^k|n

所以k要么是degree_in_fact(n,2)/5要么是degree_in_fact(n,7),取其中较小的

有趣的是,但就b=224的情况来说,上面这2个谁大谁小还和n有关。

比如n为7的时候,degree_in_fact(7,2)/5=0,degree_in_fact(7,7)=1

当n为100的时候,degree_in_fact(100,2)/5=19,degree_in_fact(100,7)=16

至于一般的规律,我也没总结出来,但是应该都是像上面这样,只有2个都算出来才知道哪个更小。

写代码之前我做了预处理,知道了小于100000的素数有9592个。

然后又把代码改写成素数打表,对p数组进行初始化。

最后写本题代码,遍历p数组达到分解b的目的。

因为b最多有6个素因子,所以及时break可以提高一些效率。

代码:

#include<iostream>
using namespace std;

int p[9592];

bool isprime(int n)
{
	for (int i = 2; i*i <= n; i++)if (n%i == 0)return false;
	return true;
}

long long degree_in_fact(long long m, int p)
{
	if (m)return degree_in_fact(m / p, p) + m / p;
	return 0;
}

int main()
{
	int k = 0;
	for (int i = 2; i < 100000; i++)if (isprime(i))p[k++] = i;
	int n, b;
	while (cin >> n >> b)
	{
		if (b == 0)break;
		int r = 1234567890;
		for (int i = 0; i < 9592; i++)
		{
			if (b%p[i])continue;
			int degree = 0;
			while (b%p[i] == 0)
			{
				b /= p[i];
				degree++;
			}
			int t = degree_in_fact(n, p[i]) / degree;
			if (r>t)r = t;
			if (p[i] > b)break;
		}
		cout << r << endl;
	}
	return 0;
}



你可能感兴趣的:(阶乘)