【数学】阶乘(fact)

L i n k Link Link

s s l   1490 ssl\ 1490 ssl 1490

D e s c r i p t i o n Description Description

【数学】阶乘(fact)_第1张图片

I n p u t Input Input

第一行有一个正整数T,表示测试数据的组数。
接下来的T行,每行输入两个十进制整数n和base。

O u t p u t Output Output

对于每组数据,输出一个十进制整数,表示在base进制下,n!结尾的零的个数。

S a m p l e Sample Sample I n p u t Input Input

2
	
10 10 

10 2

S a m p l e Sample Sample O u t p u t Output Output

2

8

H i n t Hint Hint

对于20%的数据,n<=20,base<=16

对于50%的数据,n<=10^9,base<=10^5

对于100%的数据,1<=T<=50,0<=n<=10^18,2<=base<=10^12

S o l u t i o n Solution Solution

我们可以先将 b a s e base base分解质因数
然后记录每个质因数出现的次数(例如2在6内出现了6次)
但是要注意的是, 每个质因数有它出现的次数 C p i C_{p_i} Cpi,而这就是它这个质因数重复的次数
最后只需要除一下,求最小值就好了

C o d e Code Code

#include
#include
#include
#define N 1000001
#define ll long long

using namespace std;

bool b[N]; 
ll su[N], zsu[N], C[N]; 
ll ans, tmp, T, n, base, timx;

int main()
{
	for (ll i = 2; i <= 1000000; ++i)
	{
		if (!b[i]) {
			b[i] = 1;
			su[++su[0]] = i;
			for (ll j = 2; j * i <= 1000000; ++j)
				b[i * j] = 1;
		}
	}//淳朴的素筛
	scanf("%lld", &T);
	for (ll e = 1; e <= T; ++e)
	{
		memset(C, 0, sizeof(C));
		memset(zsu, 0, sizeof(zsu));
		ans = 9223372036854775807;//每次定义初值 
		scanf("%lld%lld", &n, &base);
		tmp = base; timx = 0;
		for (ll i = 1; i <= su[0]; ++i)
		{
			if (tmp != 1) { 
				if (tmp % su[i] == 0) {
					zsu[++zsu[0]] = su[i];
					while (tmp % su[i] == 0) {
						C[zsu[0]]++;
						tmp /= su[i];
					}
				}
			}
			else break;
		}
		if (tmp > 1) {
			zsu[++zsu[0]] = tmp;
			C[zsu[0]] = 1;
		}//最后可能是一个很大的质因数
		for (ll i = 1; i <= zsu[0]; ++i)
		{
			tmp = n;
			timx = 0;
			while (tmp) {
				tmp /= zsu[i];
				timx += tmp; //记录出现的次数
			}
			ans = min(ans, timx / C[i]);
		}
		printf("%lld\n", ans);
	}
}

你可能感兴趣的:(数论,与,数学)