集训日志(二) 数学题(1):数论

 

先介绍基本概念:

 

1.同余

数论中的重要概念。给定一个正整数m,如果两个整数a和b满足a-b能被m整除,即m|(a-b),那么就称整数a与b对模m同余,记作a≡b(mod m)。对模m同余是整数的一个等价关系。

 

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、欧拉函数

  在数论,对正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目。此函数以其首名研究者欧拉命名,它又称为Euler's totient function、φ函数、欧拉商数等。
  例如φ(8)=4,因为1,3,5,7均和8互质。

 

求从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;
}


 

你可能感兴趣的:(算法,数论,数学,ACM)