两个数 n 和 k 判断k能否整除 n!
思路:
任何一个正整数 n=p1^(x1)*p2^(x2)……*pn^(xn); 其中p1,p2.……pn 是素数,x1,x2,……xn 是各个素数的指数(也就是该质因数的个数)
将k分解质因数,并记录各个质因数的个数
分别用 2……n的数去除以k的质因数,每除一次就使k的质因数的个数减一,直到为零,最后遍历记录k的质因数个数的数组,只要有大于零的,就表示k不能整除n!
到这里基本上都对了,但是要注意的是,
1 数据范围是2^31 不是2^31-1 所以会发生溢出,要用大一点的类型,我用的是unsigned;
2 要注意 当k==0的时候是不能够整除任何数的
3 当k<=n时一定可以整除n!
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
unsigned num[1000];
unsigned num1[1000];
unsigned n,m;
int totle;
void getPrim(unsigned n)
{
memset(num,0,sizeof(num));
memset(num1,0,sizeof(num1));
unsigned i;
totle=0;
if(n%2==0)
{
num[totle]=2;
while(n%2==0)
{
n/=2;
num1[totle]++;
}
totle++;
}
i=3;
while(i<=((unsigned)sqrt((double)n)+1))
{
if(n%i==0)
{
num[totle]=i;
while(n%i==0)
{
num1[totle]++;
n/=i;
}
totle++;
}
i+=2;
}
if(n>1)
{
num[totle]=n;
num1[totle]++;
totle++;
}
}
int jugde(unsigned n,unsigned m)
{
if(((n==1||n==0)&&m>1)||m==0)
{
printf("%d does not divide %d!\n",m,n);
return 1;
}
else if(m<=n)
{
printf("%d divides %d!\n",m,n);
return 1;
}
return 0;
}
unsigned solve(int n)
{
unsigned i,j;
long s=1,t;
for(i=0;i<totle;i++)
{
for(j=num[i];j<=n;j+=num[i])
{
t=j;
while(t%num[i]==0&&num1[i]>0)
{
num1[i]--;
t/=num[i];
}
while(s%num[i]==0&&num1[i]>0)
{
s/=num[i];
num1[i]--;
}
if(t!=j)
s*=t;
}
}
for(i=0;i<totle;i++)
if(num1[i]>0) return 0;
return 1;
}
int main()
{
unsigned t;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(jugde(n,m)) continue;
getPrim(m);
t=solve(n);
if(t==0)
printf("%d does not divide %d!\n",m,n);
else
printf("%d divides %d!\n",m,n);
}
return 0;
}
还有一个定理: n!中某一素数p的个数sum
for(i=p;i<=n;i*=p)
{
sum+=n/i;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
long num[100],num1[100];
long n,k,l;
long jugdeNum(long n,long numi)
{
long i,sum;
sum=0;
for(i=numi;i<=n;i*=numi)
sum+=n/i;
return sum;
}
void getPriem(unsigned numa)
{
l=0;
memset(num,0,sizeof(num));
memset(num1,0,sizeof(num1));
long i,j=0;
if(numa%2==0)
{
while(numa%2==0)
{
num1[j]++;
numa/=2;
}
num[j]=2;
j++;
}
i=3;
while(i<=((unsigned)sqrt((double)numa)+1))
{
if(numa%i==0)
{
while(numa%i==0)
{
num1[j]++;
numa/=i;
}
num[j]=i;
j++;
}
i+=2;
}
if(numa>1)
{
num[j]=numa;
num1[j]=1;
j++;
}
l=j;
}
int main()
{
unsigned i;
while(scanf("%ld%ld",&n,&k)!=EOF)
{
if(k==0||((n==0||n==1)&&k>1))
{
printf("%ld does not divide %ld!\n",k,n);
continue;
}else if(k<=n)
{
printf("%ld divides %ld!\n",k,n);
continue;
}
getPriem(k);
int flag=0;
for(i=0;i<l;i++)
if(jugdeNum(n,num[i])<num1[i])
{
flag=1;
break;
}
if(flag==1)
printf("%ld does not divide %ld!\n",k,n);
else
printf("%ld divides %ld!\n",k,n);
}
return 0;
}
这个看起来比较简单