整除问题:给定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)

输出:

一个整数.

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

我看了很多博文,很多人写出来的代码其实是有bug的。此处首先先算出较小的数a的所有素因数,讲解可以看我的前一篇博文“ 

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

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

#include
#include

#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]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;
}



黑框运行结果:

整除问题:给定n,a求最大的k,使n!可以被a^k整除但不能被a^(k+1)整除_第1张图片




你可能感兴趣的:(考研复试上机,数学问题)