您的位置:首页 > 其它

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开始算

以下是我的代码:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: