先介绍基本概念:
1.同余
2.线性筛素数法
普通筛素数法很简单:对于不超过n的每个非负整数p,删除2p,3p,4p.....当处理完所有素数后,还没有被删除的就是素数。如果用vis[i]表示i已经被删除,那么代码可以写成这样:
memset(vis,0,sizeof(vis)); for (int i = 2; i <= n ;i++) for (int j = 2*i,j<=n; j +=i) vis[j]=1;
很好证明,这种筛选素数的方法时间复杂度为O(n*logn)。不知道你发现没有,这种算法里面一个元素被删了好多次,有没有办法优化成线性时间?当然可以。
我们对每个素数p考虑所有i ,如果i 的最小素因子>=p 那么可以断定 i*p 不可能是素数。用代码实现就是:
memset(Prime,0,sizeof(Prime)); memset(IsPrime,1,sizeof(IsPrime)); for (int i=2;i<=n;i++){ if (IsPrime[i]) Prime[num++] = i; for (int j=1;j<num && i*Prime[j]<=n;j++){ IsPrime[i*Prime[j]] = 0; if (i%Prime[j] == 0) break; } }
3、欧拉函数
求从1到n-1与n互质的数的个数,代码如下 int eular(int n) { int ret = 1,i; for (i = 2;i * i <= n;i++) if (n % i == 0) { n /= i; ret *= (i - 1); while (n % i == 0) { n /= i; ret *= i; } } if (n > 1) ret *= (n - 1); return ret; }