整除问题:给定n,a求最大的k,使n!能够被a^k整除但不能被a^(k+1)整除

题目描述:

给定n,a求最大的k,使n!能够被a^k整除但不能被a^(k+1)整除。数组

输入:

两个整数n(2<=n<=1000),a(2<=a<=1000)spa

输出:

一个整数..net

样例输入:
6 10
样例输出:
1
本题目不采用轮流试的暴力解法,由于n若足够大,好比1000!实则是一个很大的数(至关大,超出想象)。 因而咱们想一下,既然要求整除,说明两个数n!的素因数与a的每一个素因数都是能够抵消的,这样咱们就能够求解了。

我看了不少博文,不少人写出来的代码实际上是有bug的。此处首先先算出较小的数a的全部素因数,讲解能够看个人前一篇博文“ code

C语言求最大公约数、最小公倍数

”。再而就是用a的素因数去试探n!(这里实际上是试探n,非n!)

#include<stdio.h>
#include<math.h>

#define  INF 32767

int prime[200];
int primesize;
bool mark[1000];

void init()
{//素数筛法:求出1~1000内的全部素数,并保存在prime素组中
	primesize = 0;
	for (int i = 0; i < 1000; i++)							//初始化
		mark[i] = false;
	for (int i = 2; i < 1000; i++)
		if(mark[i]==true) continue;
		else
		{
			prime[primesize++]=i;
			for (int j = i; j < 1000; j+=i)
				mark[j]=true;
		}
}

int main()
{
	int n,a;
	int sqrtnum;
	int prime_num;
	int primeofa[200][2];									//二维数组,第一维保存a的素因数值,二维保存其幂指数(次方)
	init();
	while (scanf("%d%d",&n,&a)!=EOF)
	{
		prime_num=0;
		sqrtnum = (int)sqrt(double(a))+1;
		for (int i = 0; i < 200; i++) primeofa[i][1]=0;
		for (int i = 0; i < primesize && prime[i]<sqrtnum;i++)//分解出a的全部素因数
		{
			if(a%prime[i]==0)								//prime[i]是n的素因数
			{
				primeofa[prime_num][0]=prime[i];
				while (a%prime[i]==0)
				{
					primeofa[prime_num][1]++;
					a/=prime[i];
				}
				prime_num++;
			}
			if(a==1) break;
		}
		if (a!=1)
		{
			primeofa[prime_num][0]=a;
			primeofa[prime_num][1]++;
			prime_num++;
		}
		int j;
		bool CanDivde = true;											//n!可否整除a标志
		int count_min=INF;
		int c=0;
		for (int i = 0; i < prime_num&&CanDivde; i++)					//本循环求出n!是a的k倍
		{
			j=1;
			if(n/primeofa[i][0]==0) CanDivde = false;					//a的某个素因数不是n!的因数,n!不能被a整除
			else
			{
				c= 0;
				while(n/primeofa[i][0]>0)								//若该a的素因数也是n!的素因数
				{
					int pownum =(int)pow(double(primeofa[i][0]),double(j));//取素因数的j次方
					c+=n/pownum;										//累加该素因数的幂指数
					j++;
					if(n/pownum==0) break;								//该素因数的幂指数个数统计完毕,退出
				}
				if(c < primeofa[i][1]) CanDivde = false;				//a与n!存在相同的素因数,但该素因数在a中的次数高于n!中的,n!也不能被a整除
				else c /= primeofa[i][1];								//求n!中该素因数幂指数是a中该幂指数的倍数
				if(count_min>c) count_min = c;							//找出最小倍数,即为所求
			}
		}
		if(CanDivde) printf("%d\n",count_min);							//该值即为所求
		else printf("-1\n");											//n!不能整除a在输出-1
	}
	return 0;
}

黑框运行结果: