又称为 算术基本定理
任何一个大于1的自然数 ,如果 N N N不为质数,都可以唯一分解成有限个质数的乘积 N = P 1 a 1 P 2 a 2 . . .   P n a n N=P_1^{a_1}P_2^{a_2}...\,P_n^{a_n} N=P1a1P2a2...Pnan,这里 P 1 < P 2 < . . .   < P n P1\lt P_2\lt...\,\lt P_n P1<P2<...<Pn均为质数,其诸指数 a i a_i ai是正整数。
这样的分解称为 N N N的标准分解式。
N N N的正因数个数: σ 0 ( N ) = ( 1 + a 1 ) ( 1 + a 2 ) . . . ( 1 + a n ) \sigma_0(N)=(1+a_1)(1+a_2)...(1+a_n) σ0(N)=(1+a1)(1+a2)...(1+an),其中 a i a_i ai为 N N N的标准分解中各质数的指数。
N N N的全体正因数之和: σ 1 ( N ) = ( 1 + P 1 + P 1 2 + . . .   + P 1 a 1 ) ( 1 + P 2 + P 2 2 + . . .   + P 2 a 2 ) . . .   ( 1 + P n + P n 2 + . . .   + P n a n ) \sigma_1(N)=(1+P_1+P_1^2+...\,+P_1^{a_1})(1+P_2+P_2^2+...\,+P_2^{a_2})...\,(1+P_n+P_n^2+...\,+P_n^{a_n}) σ1(N)=(1+P1+P12+...+P1a1)(1+P2+P22+...+P2a2)...(1+Pn+Pn2+...+Pnan)
结合等比数列求和公式,可推得: σ 1 ( N ) = 1 − P 1 a 1 + 1 1 − P 1 ⋅ 1 − P 2 a 2 + 1 1 − P 2 ⋅ . . .   ⋅ 1 − P n a n + 1 1 − P n \sigma_1(N)=\frac{1-P_1^{a_1+1}}{1-P_1}\cdot\frac{1-P_2^{a_2+1}}{1-P_2}\cdot...\,\cdot\frac{1-P_n^{a_n+1}}{1-P_n} σ1(N)=1−P11−P1a1+1⋅1−P21−P2a2+1⋅...⋅1−Pn1−Pnan+1
对于:
a = p 1 a 1 ⋅ p 2 a 2 ⋅ p 3 a 3 ⋯ p n a n a=p_1^{a_1}\cdot p_2^{a_2}\cdot p_3^{a_3} \cdots p_n^{a_n} a=p1a1⋅p2a2⋅p3a3⋯pnan
b = p 1 b 1 ⋅ p 2 b 2 ⋅ p 3 b 3 ⋯ p n b n b=p_1^{b_1}\cdot p_2^{b_2}\cdot p_3^{b_3} \cdots p_n^{b_n} b=p1b1⋅p2b2⋅p3b3⋯pnbn
有:
gcd ( a , b ) = p 1 min ( a 1 , b 1 ) ⋅ p 2 min ( a 2 , b 2 ) ⋅ p 3 min ( a 3 , b 3 ) ⋯ p n min ( a n , b n ) \gcd(a,b)=p_1^{\min(a_1,b_1)}\cdot p_2^{\min(a_2,b_2)}\cdot p_3^{\min(a_3,b_3)}\cdots p_n^{\min(a_n,b_n)} gcd(a,b)=p1min(a1,b1)⋅p2min(a2,b2)⋅p3min(a3,b3)⋯pnmin(an,bn)
l c m ( a , b ) = p 1 max ( a 1 , b 1 ) ⋅ p 2 max ( a 2 , b 2 ) ⋅ p 3 max ( a 3 , b 3 ) ⋯ p n max ( a n , b n ) lcm(a,b)=p_1^{\max(a_1,b_1)}\cdot p_2^{\max(a_2,b_2)}\cdot p_3^{\max(a_3,b_3)}\cdots p_n^{\max(a_n,b_n)} lcm(a,b)=p1max(a1,b1)⋅p2max(a2,b2)⋅p3max(a3,b3)⋯pnmax(an,bn)
每个合数都可以写成几个质数相乘的形式,其中每个质数都是这个合数的因数,把一个合数用质因数相乘的形式表示出来,实际上就是 得到 N N N的标准分解式。
先得到素数表,然后遍历拆分即可。对于 N N N,只需要得到 1 1 1~ N \sqrt N N的素数表即可,即 m a x n = N maxn=\sqrt N maxn=N
int prime[maxn],tot;
bool vis[maxn];
void get_prime() //欧拉筛得到素数表
{
memset(vis,0,sizeof(vis));
tot=0;
for(int i=2;i<=maxn;i++)
{
if(!vis[i])
prime[++tot]=i;
for(int j=1;j<=tot&&i*prime[j]<=maxn;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0)
break;
}
}
}
int p[maxn],a[maxn],cnt;
void get_prime_factor(int n)
{
cnt=0;
for(int i=1;prime[i]*prime[i]<=n;i++)
{
if(n%prime[i]==0)
{
cnt++;
p[cnt]=prime[i]; //质因数
a[cnt]=0; //对应指数
while(n%prime[i]==0)
{
a[cnt]++; //统计个数
n/=prime[i];
}
}
if(n==1)
break;
}
if(n>1) //不要漏了这句
{
cnt++;
p[cnt]=n;
a[cnt]=1;
}
}
很明显,对于 n ! n! n!,其质因数肯定 包括 1 1 1~ n n n的所有质数,只是各质数的个数(指数)尚不确定(至少为 1 1 1)。
8 ! 8! 8!: 1 × 2 × 3 × 4 × 5 × 6 × 7 × 8 1\times2\times3\times4\times5\times6\times7\times8 1×2×3×4×5×6×7×8,以质因数 2 2 2为例
其中 2 2 2的倍数: 2 , 4 , 6 , 8 2,4,6,8 2,4,6,8,共 4 4 4个
其中 4 4 4的倍数: 4 , 8 4,8 4,8,共 2 2 2个
其中 8 8 8的倍数: 8 8 8,共 1 1 1个
参考blog:https://www.cnblogs.com/Slager-Z/p/7780382.html
所以质因数 2 2 2在分解式中的指数为 4 + 2 + 1 = 7 4+2+1=7 4+2+1=7个,这样就可以有效避免重复统计。
即 c n t ( 2 ) = 8 / 2 + 8 / 2 / 2 + 8 / 2 / 2 / 2 cnt(2)=8/2+8/2/2+8/2/2/2 cnt(2)=8/2+8/2/2+8/2/2/2,这个计算过程可以很简单地用递归实现:
int cal(int n,int p) //计算n!中质因数p的个数(指数)
{
if(n==0)
return 0;
return cal(n/p,p)+n/p;
}
完整代码:
int prime[maxn],tot;
bool vis[maxn];
void get_prime() //欧拉筛得到素数表
{
memset(vis,0,sizeof(vis));
tot=0;
for(int i=2;i<=maxn;i++)
{
if(!vis[i])
prime[++tot]=i;
for(int j=1;j<=tot&&i*prime[j]<=maxn;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0)
break;
}
}
}
int cal(int n,int p) //计算n!中质因数p的个数(指数)
{
if(n==0)
return 0;
return cal(n/p,p)+n/p;
}
int p[maxn],a[maxn];
void get_prime_factor(int n)
{
for(int i=1;prime[i]<=n;i++)
{
p[i]=prime[i];
a[i]=cal(n,prime[i]);
}
}
待补充…