zoukankan      html  css  js  c++  java
  • 积性函数的线性求法

    首先我们来了解一下积性函数的定义。

    (forall x,y)满足(gcd(x,y)=1),有(f(xy)=f(x)f(y))的数论函数称为积性函数。若(forall x,y)均有(f(xy)=f(x)f(y)),则称为完全积性函数

    然后我们要理解线性素数筛。

    void getP(int n)
    {
        for(int i=2;i<=n;i++)
        {
            if(!notP[i]) P[++cntP]=i;
            for(int j=1;j<=cntP&&i*P[j]<=n;j++)
            {
                notP[i*P[j]]=true;
                if(i%P[j]==0) break;
            }
        }
        for(int i=1;i<=cntP;i++) printf("%d ",P[i]);
    }
    

    if(i%P[j]==0) break;保证了每个数只会被其最小的质因子筛掉一次,所以复杂度为(O(n))。用反证法证明:假设(x)最小的质因子为(p_0),而(x)是被(i imes p_j(p_j>p_0))筛掉的,那么必然有(p_0|i),在循环到(j)之前已经break了,矛盾。

    那么接下来我们就可以来看线性求积性函数的代码了,这里以欧拉函数(varphi(n))为例。

    void getF(int n)
    {
        f[1]=1,p1[1]=1;
        for(int i=2;i<=n;i++)
        {
            if(!notP[i])
            {
                P[++cntP]=i;
                for(lint j=i;j<=n;j*=i) f[j]=j-j/i,p1[j]=j;    //1
            }
            for(int j=1;j<=cntP&&i*P[j]<=n;j++)
            {
                int x=i*P[j]; notP[x]=true;
                if(i%P[j]) f[x]=f[i]*f[P[j]],p1[x]=P[j];
                else {f[x]=f[i/p1[i]]*f[p1[i]*P[j]],p1[x]=p1[i]*P[j]; break;}
            }
        }
        for(int i=1;i<=n;i++) printf("%lld ",f[i]); puts("");
    }
    

    将正整数(x)表示为(prod_{i=1}^k p_i^{q_i})的形式,其中(p_i)是递增的。
    (cntP)(P[N])存储质数,(f[x])记录函数的值,(p1[x])记录(x)(p_1^{q_1})
    主要分析13,14行。
    if(i%P[j]) f[x]=f[i]*f[P[j]],p1[x]=P[j]; 因为(igeq P_j)(i mod P_j eq 0),所以(gcd(i,P_j)=1)(f(icdot P_j)=f(i)f(P_j))(P_j)(icdot P_j)最小的质因子且只有一个,所以(p1[icdot P_j]=P_j)
    else {f[x]=f[i/p1[i]]*f[p1[i]*P[j]],p1[x]=p1[i]*P[j]; break;}易知(f(xcdot p_1)=f(dfrac{x}{p_1^{q_1}})f(p_1^{q_1+1})),而(P_j)恰是(i)(p_1)(icdot P_j=p_1 prod_{t=1}^k p_t^{q_t}=p_1^{q_1+1}prod_{i=2}^k p_i^{q_i}),所以(p1[icdot P_j]=p_1^{q_1+1}=p1[i]cdot P_j)。本行的break和素数筛一样保证了复杂度为(O(n))
    不过当(x=p_1^{q_1})时无法使用这个公式,所以要将注释1处的代码替换掉。

  • 相关阅读:
    连分数与丢番图方程简介
    利用 random 与 tertools 模块解决概率问题
    Notepad++ 几款实用插件简介,让你的 Notepad++ 如虎添翼
    .net面试问答(大汇总)
    .net反射详解 原文://http://blog.csdn.net/wenyan07/article/details/27882363
    ASP.NET MVC4+EF5(Lambda/Linq)读取数据
    AngularJS+ASP.NET MVC+SignalR实现消息推送
    Asp.net SignalR 实现服务端消息推送到Web端
    C# Socket编程 同步以及异步通信
    C#版 Socket编程(最简单的Socket通信功能)
  • 原文地址:https://www.cnblogs.com/VisJiao/p/8735603.html
Copyright © 2011-2022 走看看