分析 由唯一分解定理,我们可知道 m=p1^r1*p2^r2……pn^rn (p为素数)。
如果n!要想被m整除,必须也至少有 p1^r1*p2^r2……pn^rn 。
另外
注意在O(log n / log p)时间内求出n!的质因子分解中质数p的指数:(勒让德定理的简化算法)
inline int getn(int n, int p)
{
int sum = 0;
while (n)
{
n /= p;
sum += n;
}
return sum;
}
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std ;
typedef long long LL ;
const int MAXN = 1e5+100;
const int MAXM = 1e5 ;
const int mod = 1007 ;
const int inf = 0x3f3f3f3f;
int su[MAXN],prm[MAXN],sz=0;
void init(){
for(int i=2;i<MAXN;i++) {
if(!su[i]) prm[sz++]=i;
for(int j=0;j<sz;j++) {
int t=i*prm[j];
if(t>=MAXN) break;
su[t]=1;
if(i%prm[j]==0) break;
}
}
}
int getn(int n,int p){
LL cnt=0;
while(n){
n/=p;
cnt+=n;
}
return cnt;
}
bool solve(int n,int m ){
for(int i=0;i<sz&&(LL)(prm[i]*prm[i])<=m;i++){ // 注意这里会爆 LL
if(m%prm[i]==0){
int cnt=0;
while(m%prm[i]==0){
cnt++;m/=prm[i];
}
if(getn(n,prm[i])<cnt) return 0;// 说明不能够符合条件
}
}
if(m>1&&n<m) return 0;// 说明m自身是一个大素数
return 1;
}
int main(){
int n,m;
init();
while(~scanf("%d%d",&n,&m)) {
if(n==1){
if(m==1) printf("%d divides %d!\n", m, n);
else printf("%d does not divide %d!\n", m, n);
continue;
}
if(solve(n,m)) printf("%d divides %d!\n", m, n);
else printf("%d does not divide %d!\n", m, n);
}
return 0;
}