zoukankan      html  css  js  c++  java
  • noip复习——线性筛(欧拉筛)

    整数的唯一分解定理:
    (forall Ain mathbb {N} ,\,A>1quad exists prodlimits _{i=1}^{s}p_{i}^{a_{i}}=A),其中({displaystyle p_{1}<p_{2}<p_{3}<cdots <p_{s}})而且 (p_{i})是一个质数, (a_{i}in mathbb {Z} ^{+})(摘自维基百科)

    欧拉筛通过使每个整数只会被它的最小质因子筛到来保证时间复杂度,可以用来筛质数。同时,利用这个性质可以在线性时间内筛出很多积性函数。


    筛质数

    for (int i = 2; i <= n; ++i)
    {
        if (!vis[i])
        	pri[++cnt] = i;
        for (int j = 1; j <= cnt && pri[j] * i <= n; ++j)
        {
            vis[i * pri[j]] = 1;
            if (i % pri[j] == 0)
            	break;
        }
    }
    

    求欧拉函数(varphi)

    欧拉函数为1~n中和n互质的数的个数

    所以如果(n=p^k), (p)是质数,那么(varphi(n)=varphi(p^k)=p^k - p^{k-1}=p^{k-1}(p-1)=p^{k-1}varphi(p)=p varphi(p^{k-1}))

    结论很显然,因为除了(p)的倍数外,其他数都和(n)互质

    所以在欧拉筛的时候,如果(i)是素数,那么(varphi(i)=i-1)

    如果(i mod pri[j]==0),也就是说(pri[j])(i * phi[j])中出现了至少两次,那么(varphi(i * pri[j])=pri[j]*varphi(i))

    而如果(i mod pri[j]!=0),也就是(phi[j])(i * phi[j])中第一次出现,那么(gcd(i, phi[j])==1),因为(varphi)是积性函数,所以(varphi(i * pri[j])=varphi(pri[j])*varphi(i))

    for (int i = 2; i <= n; ++i)
    {
        if (!vis[i])
        	pri[++cnt] = i,
        	phi[i] = i - 1;
        for (int j = 1; j <= cnt && pri[j] * i <= n; ++j)
        {
            vis[i * pri[j]] = 1;
            if (i % pri[j])
                phi[i * pri[j]] = phi[i] * phi[pri[j]];
            else
            {
                phi[i * pri[j]] = phi[i] * pri[j];
                break;
            }
        }
    }
    

    求莫比乌斯函数(mu)

    (mu (n)={egin{cases}1 qquadquad (n=1)\(-1)^{s}quad (n无平方因子,s为素因子个数)\0qquadquad else\end{cases}})

    然后就,照着定义来行了

    for (int i = 2; i <= n; ++i)
    {
        if (!vis[i])
        	pri[++cnt] = i,
        	mu[i] = -1;
        for (int j = 1; j <= cnt && pri[j] * i <= n; ++j)
        {
            vis[i * pri[j]] = 1;
            if (i % pri[j])
                mu[i * pri[j]] = -mu[i];
            else
                break;
        }
    }
    

    求约数个数(sigma_0/d)

    (d(n)=sumlimits_{i=1}^s{(a_i+1)}), 另定义(f(n)=a_1)(quad(a、s定义见上文))

    和欧拉函数类似。 如果(i)是素数,那么(d(i)=2,f(i)=1)

    如果(i mod pri[j]==0),也就是说(pri[j])(i * phi[j])中出现了至少两次,那么(f(i * pri[j])=f(i)+1,d(i*pri[j])=d(i)/(f(i)+1)*(f(i)+2))(quad(消去pri[j]对i的影响,乘上pri[j]对i *pri[j]的影响))

    而如果(i mod pri[j]!=0),也就是(phi[j])(i * phi[j])中第一次出现,那么(gcd(i, phi[j])==1),因为(d)是积性函数,所以(d(i * pri[j])=d(pri[j])*d(i))

    for (int i = 2; i <= n; ++i)
    {
        if (!vis[i])
        	pri[++cnt] = i,
        	f[i] = 1,
        	d[i] = 2;
        for (int j = 1; j <= cnt && pri[j] * i <= n; ++j)
        {
            vis[i * pri[j]] = 1;
            if (i % pri[j])
                f[i * pri[j]] = 1, d[i * pri[j]] = d[i] * d[pri[j]];
            else
            {
            	f[i * pri[j]] = f[i] + 1;
                d[i * pri[j]] = d[i] / (f[i] + 1)* (f[i] + 2);
                break;
            }
        }
    }
    
  • 相关阅读:
    CompositeConfiguration的用法
    Intellij IDEA连接Git@OSC
    Spring4.1.6 标签注解大全以及解释
    React制作吸顶功能总结
    总结常见的ES6新语法特性。
    12个常规前端面试题及小结
    JavaScript 扩展运算符
    Promise,Generator(生成器),async(异步)函数
    Vue中过度动画效果应用
    vue的双向绑定原理及实现
  • 原文地址:https://www.cnblogs.com/happyLittleRabbit/p/10840167.html
Copyright © 2011-2022 走看看