阶乘分解

CH

题意:给定整数\(N(N<=10^6)\),试把\(N!\)分解质因数,按照算数基本定理的形式输出\(p_i\)\(c_i\)即可。

分析:\(N!\)中每个质因子都不会超过N,考虑筛出\(1~N\)的所有质数p,\(N!\)中质因子p的个数就等于\(1~N\)每个数包含质因子p的个数之和.在\(1~N\)中,p的倍数,即至少包含一个质因子p的有\([\frac Np]\)个,而\(p^2\)的倍数,即至少包含两个质因子p的有\([\frac N{p^2}]\)个,不过其中一个已经在\([\frac Np]\)中统计过了,所以只需要统计第二个质因子,即累加上\([\frac N{p^2}]\)就行了.

所以\(N!\)中质因子p的个数为\([\frac Np]+[\frac N{p^2}]+...+[\frac N{p^{[log_pN]}}]=\sum_{p^k<=N} [\frac N{p^k}]\).

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
const int N=1000005;
int m,n,v[N],prime[N];
inline void get_prime(){
    for(int i=2;i<=n;i++){
		if(!v[i]){
	    	v[i]=i;
	    	prime[++m]=i;
		}
		for(int j=1;j<=m;j++){
	    	if(prime[j]>v[i]||prime[j]*i>n)break;
	    	v[prime[j]*i]=prime[j];
		}
    }
}
int main(){
    n=read();get_prime();
    for(int i=1;i<=m;i++){	
		long long p=prime[i];int ans=0;
		while(p<=n){
	    	ans+=floor(n/p);
	    	p*=prime[i];
		}
//这样写也可以:
		/*int nn=n;
		while(nn){
	    	ans+=nn/prime[i];
	    	nn/=prime[i];
		}*/
		printf("%d %d\n",prime[i],ans);
    }
    return 0;
}

posted on 2019-06-10 07:55  PPXppx  阅读(225)  评论(0编辑  收藏  举报