九度1104:整除问题

来源:互联网 发布:数据库建模工具有哪些 编辑:程序博客网 时间:2024/06/05 10:36
题目描述:

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

输入:

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

输出:

一个整数.

样例输入:
6 10
样例输出:
1
来源:

2011年上海交通大学计算机研究生机试真题


思路:
a^k和n!都可能非常大,甚至超过long long int的表示范围,所以也就不能直接用取余操作判断它们之间是否存在整除关系,因此我们需要换一种思路,从分解质因数入手,假设两个数a和b:
a = p1^e1 * p2^e2 * ... * pn^en,  b = p1^d1 * p2^d2 * ... * pn^dn, 则b除以a可以表示为:
b / a = (p1^d1 * p2^d2 * ... * pn^dn) / (p1^e1 * p2^e2 * ... * pn^en)
若b能被a整除,则 b / a必为整数,且两个素数必互质,则我们可以得出如下规律:
若a存在质因数px,则b必也存在该质因数,且该素因数在b中对应的幂指数必不小于在a中的幂指数
另b = n!, a^k = p1^ke1 * p2^ke2 * ... * pn^ken,因此我们需要确定最大的非负整数k即可。要求得该k,我们只需要依次测试a中每一个素因数,确定b中该素因数是a中该素因数的幂指数的多少倍即可,所有倍数中最小的那个即为我们要求得的k
分析到这里,剩下的工作似乎只是对a和n!分解质因数,但是将n!计算出来再分解质因数,这样n!数值太大。考虑n!中含有素因数p的个数,即确定素因数p对应的幂指数。我们知道n!包含了从1到n区间所有整数的乘积, 这些乘积中每一个p的倍数(包括其本身)都对n!贡献至少一个p因子,且我们知道在1到n中p的倍数共有n/p个。同理,计算p^2,p^3,...即可

#include <stdio.h>  #include <stdlib.h>  #include <string.h>     #define N 1001  int prime[N],size;void initprime(){   // 求1000内的质数 int i,j;prime[0]=prime[1];for(i=2;i<N;i++)prime[i]=1;size=0;for(i=2;i<N;i++){if(prime[i]){for(j=i*2;j<N;j=j+i)prime[j]=0;size++;}}}int main(){int n,a,i,j,k,*abase,*anum;while(scanf("%d%d",&n,&a)==2){initprime();abase = (int *)calloc(size, sizeof(int));          anum = (int *)calloc(size, sizeof(int));         j=0;//分解a for(i=2;i<N&&a!=1;i++){if(prime[i]&&a%i==0){abase[j]=i;anum[j]=0;while(a!=1&&a%i==0){anum[j]+=1;a=a/i;}j++;}}k=0x7fffffff;                     //求K int base,tempk,count;for(i=0;i<j;i++){base=abase[i];count=0;while(base<=n){count+=n/base;base*=abase[i];}tempk=count/anum[i];if(tempk<k)k=tempk;}printf("%d\n",k);}return 0;}


0 0