• 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;
            }
        }
    }
    
  • 相关阅读:
    使用crypto-js对数据进行加密 解密
    immutable 入门基础
    Redux与mobx对比我们应该如何选择?
    Redux使用实例/学习笔记
    java踩坑之mysql时区与系统不同步问题
    Spring Boot学习之初识Spring Boot
    Spring MVC之表单标签库和校验注解
    Spring MVC之自定义数据转换器和REST
    Spring MVC之数据绑定和模型数据解析
    Spring MVC 之什么是Spring MVC?
  • 原文地址:https://www.cnblogs.com/happyLittleRabbit/p/10840167.html
Copyright © 2020-2023  润新知