纪中暑假集训 2020.08.13【NOIP提高组】模拟 T1:【GDKOI2014】阶乘

【GDKOI2014】阶乘

Description

在这里插入图片描述

Input

第一行有一个正整数T,表示测试数据的组数。

接下来的T行,每行输入两个十进制整数n和base。

Output

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

Sample Input

2

10 10

10 2

Sample Output

2

8

Data Constraint

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

对于50%的数据,n<=109,base<=105

对于100%的数据,1<=T<=50,0<=n<=1018, 2<=base<=1012

反思&题解

比赛&正解思路: 我们回忆一下转进制的过程,答案就是 n ! n! 一直除以base的余数开始连续0的个数,所以我们很自然地就想到了分解质因数,首先我们先将base分解一下质因数,对于每一个质因子去处理,假设当前处理2这个质因子,n等于是10,我来模拟一下这个过程(下面的除法都取整除):
首先10以内包含1个2的:2,4,6,8,10 共5个 ——— 10/2=5(个)
包含2个2的:4,8,共2个 ——— 5/2=2(个)
包含3个2的,8,共1个 ——— 2/2=1(个)
之后 10 ! 10! 里面一共可以取出5+2+1=8个2
对于每个质因子都进行这样的操作计算出一共可以取出多少个,再去整除从base里面分解出来的这个质因子的个数,得到的所有商取最小的就行了,因为同时都包含的相对个数的商才是合法的答案(这应该很好理解吧)
反思: 终于靠着自己的分析做出一道数学题了 (我太弱了(ノ=Д=)ノ)

CODE

#include<bits/stdc++.h>
using namespace std;
long long const inf=1e17;
long long t,n,base,zyz[1000005],num[1000005],ans;
int main()
{
	scanf("%lld",&t);
	while (t--)
	{
		memset(zyz,0,sizeof(zyz));
		memset(num,0,sizeof(num));
		scanf("%lld%lld",&n,&base);
		long long base1=base,i;
		for (i=2;i<=sqrt(base1);i++)
		{
			if (base==1) break;
			if (base%i==0)
			{
				num[++num[0]]=i;
				while (base%i==0)
				{
					zyz[num[0]]++;
					base/=i;	
				}	
			}
		}
		if (base>1)
		{
			num[++num[0]]=base;
			zyz[num[0]]=1;
		}
		ans=inf;
		for (i=1;i<=num[0];i++)
		{
			long long nn=n,tot=0;
			while (nn>0)
			{
				nn/=num[i];
				tot+=nn;
			}
			if (tot/zyz[i]<ans) ans=tot/zyz[i];
		}
		printf("%lld\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CMC_YXY/article/details/107989310