小于n且与n互素的整数个数(欧拉函数)的计算

即计算1~n中与n互素的整数个数

互素就是无法被n整除的数("与p互素"和"不是p的倍数"是等价的)

所以第一种显而易见的方法就是暴力枚举法,但效率太低。

第二种方法用唯一分解定律再运用容斥原理:


分解定律:分为n=p1^a1*p2^a2......pk^ak;


容斥原理:在计数时,要保证无一重复,无一遗漏。为了使重叠部分不被重复计算,在不考虑重叠的情况下,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。

也即是A∪B∪C=A+B+C-A∩B-B∩C-C∩A+A∩B∩C

于是可以总结出规律:偶数项相加,奇数项相减


所以1~n中与n互素的整数个数= n-p1,p2,p3,p4.....pk的倍数(即-n/p1-n/p2-n/p3...)

                                                      + p1*p2,p1*p3....的倍数(即n/(p1*p2)+n/(p1*p3)....)

                                                       - p1*p2*p3,p1*p2*p4.......的倍数(即-n/(p1*p2*p3)-n/(p1*p2*p4).....)以此类推

这个数算出来就是欧拉函数,即 φ(N)=N*(1-1/P1)*(1-1/P2)*...*(1-1/Pn);

尝试展开这个公式就会发现与上面那个推导的式子一样,假如从括号中任选一个值出来乘就会发现偶数项为正,奇数项为负,且项与上式一样;


对于求φ(N)只需循环计算得出值就好了


对于求1~n中所有欧拉函数的值不需要依次计算

#include
#include
#include
#include
#include
#include
using namespace std;
void phi_table(int n,int *phi)
{
	for(int i=1;i<=n;i++) phi[i]=0;
	phi[0]=1;
	for(int i=2;i<=n;i++)
	if(!phi[i])               //每一项i都是素数
	for(int j=i;j<=n;j+=i)     //i的倍数肯定都包含这个素因数 
	{
		if(!phi[j]) phi[j]=j;  //未计算的初始化为j,为了计算式子n*(1-1/p)中的n;
		phi[j]=phi[j]/i*(i-1);
	}
}
int main()
{
	int phi[100+5];
	phi_table(100,phi);
	for(int i=1;i<=100;i++)
	cout<


你可能感兴趣的:(数学方法)