质数

积性函数

若函数 \(f(1)=1\),并且对于 \(gcd(x,y)=1,f(xy)=f(x)*f(y)\),则 \(f(i)\) 为积性函数。

若函数 \(f(1)=1\),并且 \(f(xy)=f(x)*f(y)\),则 \(f(i)\) 为完全积性函数。

除数函数,欧拉函数为积性函数。

判断单个素数


inline bool isprime(int x){
    if(x<2)return false;/*2以内不是质数*/
    int sq=sqrt(x)+1;
    for(int i=2;i<=sq;i++)if(x%i==0)return false;/*因子最多根号个,扫描每个因子*/
    return true;

}

埃氏筛

任意整数的倍数都不是倍数,标记这些倍数,没有被标记的就是质数,时间复杂度 \(O(N* \log\log N)\).


inline void sieve(int n){
    for(int i=2;i<=n;i++){
        if(!v[i])prime[++m]=i;/*没有被标记的是质数*/
        for(int j=i*i;j<=n;j+=i)v[j]=1;/*标记当前数每个倍数*/
    }
}

线性筛,即欧拉筛

控制每个数只被标记一次,即被它的最小质因子标记。


inline void sieve(int n){
    for(int i=2;i<=n;i++){
        if(!v[i])prime[++m]=i,miv[i]=i;/*i的最小质因子是i*/
        for(int j=1;j<=m&&i*prime[j]<=n;j++){
            v[i*prime[j]]=1;
            miv[i*prime[j]]=prime[j];/*i*prime[j]的最小质因子是prime[j]*/
            if(miv[i]==prime[j])break;/*当i中也含有质因子prime[j]时停止*/
        }
    }
}

筛法求约数个数

\(d_i\) 表示 \(i\) 的约数个数,\(num_i\) 表示 \(i\) 的最小质因子出现的次数。

对于 \(n=\prod_{i=1}^{m}{p_i^{c_i}}\) ,约数个数为 \(\prod_{i=1}^{m}{(c_i+1)}\).

inline void sieve(int n){
    d[1]=1;/*1的约数个数是1*/
    for(int i=2;i<=n;i++){
        if(!v[i])prime[++m]=i,d[i]=2,num[i]=1;/*质数的约数只有1和自己,最小质因子为自己,出现次数为1*/
        for(int j=1;j<=m&&i*prime[j]<=n;j++){
            v[i*prime[j]]=1;
            if(i%prime[j]){/*新出现的最小质因子*/
                num[i*prime[j]]=1;/*次数为1*/
                d[i*prime[j]]=d[i]*d[prime[j]];/*d[prime[j]]=num[prime[j]]+1=2,约数个数相乘*/
            }
            else{/*已经出现过的*/
                num[i*prime[j]]=num[i]+1;/*累加最小质因子出现次数*/
                d[i*prime[j]]=d[i]/num[i*prime[j]]*(num[i*prime[j]]+1);/*先除掉最小质因子的次数清空其影响,再重新计算*/
                break;
            }
        }
    }
}

筛法求约数和

\(f_i\) 表示 \(i\) 的约数和,\(g_i\) 表示 \(i\) 的最小质因子 \(p\)\(p^0+p^1+...p^c\).

inline void sieve(int n){
    f[1]=g[1]=1;
    for(int i=2;i<=n;i++){
        if(!v[i])prime[++m]=i,f[i]=g[i]=i+1;
        for(int j=1;j<=m&&i*prime[j]<=n;j++){
            v[i*prime[j]]=1;
            if(i%prime[j]){
                g[i*prime[j]]=prime[j]+1;
                f[i*prime[j]]=f[i]*f[prime[j]];
            }
            else{
                g[i*prime[j]]=g[i]*prime[j]+1;
                f[i*prime[j]]=f[i]/g[i]*g[i*prime[j]];
                break;
            }
        }
    }
}
posted @ 2022-11-19 16:48  半步蒟蒻  阅读(124)  评论(5)    收藏  举报