UVA 10139 判断n的阶乘能否被m整除
2011-04-22 17:37
344 查看
题目连接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=13&problem=1080&mosmsg=Submission+received+with+ID+8769167
题意不解释了,直接说方法。
首先观察数据范围,loss than 2^31次方,所以一般的暴力算法肯定会超时的,故需要从阶乘的本质入手
首先是一个数论的基本常识:
n!中间包含了多少个x(x是任意的一个数,不过一般情况下我们都只讨论x为质数),这种问题的答案是:
n/x+n/(x^2)+n/(x^3).....[一直加到x的乘方不超过n],这个定理的证明也非常的简单,这里就不再赘述了
然后还有一个数论的基本常识就是任意一个数的质因数分解
必须知道这种分解是唯一的
即合数y=sigma[(pi)^ni]
而且pi的范围在2——sqrt(n)之间;
于是乎,我们可以先分解掉m(这个花不了多少时间,如果用质数筛选法加速的话)
然后我们再去看m分解出来的每一个pi在n!中是否有足够多,为了提速。我们可以先从最大的pi开始算
以下是我的代码:
题意不解释了,直接说方法。
首先观察数据范围,loss than 2^31次方,所以一般的暴力算法肯定会超时的,故需要从阶乘的本质入手
首先是一个数论的基本常识:
n!中间包含了多少个x(x是任意的一个数,不过一般情况下我们都只讨论x为质数),这种问题的答案是:
n/x+n/(x^2)+n/(x^3).....[一直加到x的乘方不超过n],这个定理的证明也非常的简单,这里就不再赘述了
然后还有一个数论的基本常识就是任意一个数的质因数分解
必须知道这种分解是唯一的
即合数y=sigma[(pi)^ni]
而且pi的范围在2——sqrt(n)之间;
于是乎,我们可以先分解掉m(这个花不了多少时间,如果用质数筛选法加速的话)
然后我们再去看m分解出来的每一个pi在n!中是否有足够多,为了提速。我们可以先从最大的pi开始算
以下是我的代码:
#include<stdio.h> #include<string.h> struct node { long p; long n; node() { n=0; } }; long prime[50000]; bool flag[50000]; node stc[1000]; long num1=0,num2; void init() { unsigned long i,j; memset(flag,0,sizeof(flag)); for(i=2;i<50000;i++) { if(!flag[i]) { prime[num1++]=i; for(j=i*i;j<50000;j=j+i) flag[j]=true; } } } void devide(long m) { long i; num2=0; for(i=0;prime[i]*prime[i]<=m;i++) { if(m%prime[i]==0) { stc[num2].p=prime[i]; stc[num2].n++; m=m/prime[i]; while(m%prime[i]==0) { stc[num2].n++; m=m/prime[i]; } num2++; } if(m==1) break; } if(m>1) { stc[num2].p=m; stc[num2].n++; num2++; } } bool judge(long n,long m) { long i,sum,temp; for(i=num2-1;i>=0;i--) { sum=0; temp=stc[i].p; while(n>=temp) { sum=sum+n/temp; temp=temp*stc[i].p; } if(sum<stc[i].n) return false; } return true; } int main() { long n,m,i; init(); while(scanf("%ld%ld",&n,&m)!=EOF) { for(i=0;i<1000;i++) stc[i].n=0; if(n<=1&&m>1) { printf("%ld does not divide %ld!/n",m,n); continue; } if(m==0) { printf("%ld does not divide %ld!/n",m,n); continue; } if(n>=m) { printf("%ld divides %ld!/n",m,n); continue; } devide(m); if(judge(n,m)) printf("%ld divides %ld!/n",m,n); else printf("%ld does not divide %ld!/n",m,n); } return 0; }
相关文章推荐
- UVa 10139 Factovisors (阶乘能否整除?)
- uva 10139 求n的阶乘能否整除m
- uva1587 判断所给的六个面能否构成长方体
- UVa-10139 Factovisors -(阶乘的整除)
- UVa Problem 10139 Factovisors (阶乘与整除)
- UVa 1587 Box 判断6个面能否构成长方体
- Determine the Shape - UVa 11800 凸包判断四边形
- 幂和阶乘 UVa10780
- 09:判断能否被3,5,7整除
- NSArray不用遍历能否判断一个对象是否存在在数组里面?
- 判断是否能解析DNS 能否ping通服务器,能否链接google ,能否链接到自己的服务器
- 给定一个数组,判断从开始能否走到结束,最多需要几步?
- HDU 1325&&POJ 1308 Is It A Tree? 并查集判断能否树(能否形成环)
- Uva 1146 - Now or later 二分+构图2-sat判断
- hdoj 5505 GT and numbers 【判断一个数 能否通过累乘因子得到另一个数】【好题】
- UVA 270 Lining Up (几何 判断共线点)
- 7_5 困难的串(UVa129)<回溯法:避免无用判断>
- 快速判断一个数能否被2、3、4、5、7、9、11整除
- Uva221矩形个数判断
- UVALive 7281 Saint John Festival (凸包+O(logn)判断点在凸多边形内)