zoukankan      html  css  js  c++  java
  • 【模板】埃拉托色尼筛法 && 欧拉筛法 && 积性函数

    埃拉托色尼筛法

      朴素算法

    1 vis[1]=1;
    2 for (int i=2;i<=n;i++)
    3     if (!vis[i])
    4     {
    5         pri[++tot]=i;
    6         for (int j=i*2;j<=n;j+=i)
    7             vis[j]=1;
    8     }

    欧拉筛法

      朴素算法

     1 vis[1]=1;
     2 for (int i=2;i<=n;i++)
     3 {
     4     if (!vis[i])
     5         pri[++tot]=i;
     6     for (int j=1;j<=tot;j++)
     7     {
     8         if (i*pri[j]>n) break;
     9         vis[i*pri[j]]=1;
    10         if (i%pri[j]==0) break;
    11     }
    12 }

    以luoguP3383为例

    标程:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int prime[10000020],mark[10000020];
     4 int bj,ph[10000020];
     5 void oula(int p){
     6     ph[1]=1;
     7     for(int i=2;i<=p;i++) {
     8         if(!mark[i]){
     9             prime[++bj] = i;
    10             ph[i]=i-1;
    11         }
    12         for(int j=1;j<=bj;j++){
    13             if(i*prime[j]>p) break;
    14             mark[i*prime[j]]=1;
    15             if(i%prime[j]==0)    {
    16                 ph[i*prime[j]]=ph[i]*prime[j];
    17                 break;
    18             }
    19             else ph[i*prime[j]]=ph[i]*ph[prime[j]];
    20         }
    21     }
    22 }
    23 int n,m1;
    24 int main(){
    25     cin>>n>>m1;
    26     oula(n);
    27     for(int i=1;i<=m1;i++)  {
    28         int m;
    29         cin>>m;
    30         if(m-1!=ph[m]) cout<<"No"<<endl;
    31         else cout<<"Yes"<<endl;
    32     }
    33     return 0;
    34 }

    以下内容为转载于https://blog.csdn.net/y20070316/article/details/51729812

    二. 欧拉筛法解积性函数

    1. 方法

    步骤Ⅰ:证明积性 
    步骤Ⅱ:考虑下面三方面的实现: 
    ①素数m,求f(m) 
    ②m和比m的最小素因子小的素数n,求f(n*m) 
    ③m和m的最小素因子n:求f(n*m)

    2. 例子

    (1)欧拉函数

    题目:PC 1499

    证明:设[Math Processing Error]n=∏aipi,m=∏biqi,且[Math Processing Error]gcd(m,n)=1 
    [Math Processing Error]∴ϕ(mn)=mn∏(1−1ai)∏(1−1bi)=[n∗∏(1−1ai)]∗[m∗(∏(1−1bi)]=ϕ(n)ϕ(m)

    写法: 
    ①素数m:[Math Processing Error]ϕ(m)=m−1 
    ②m和比m的最小素因子小的素数n: 
    [Math Processing Error]ϕ(m∗n)=ϕ(m)∗phi(n) 
    ③m和m的最小素因子n:[Math Processing Error]ϕ(m∗n)=ϕ(m)∗n

     1 phi[1]=1;
     2 for (int i=2;i<=n;i++)
     3 {
     4     if (!phi[i])
     5     {
     6         pri[++tot]=i;
     7         phi[i]=i-1;
     8     }
     9     for (int j=1;j<=tot;j++)
    10     {
    11         if (i*pri[j]>n) break;
    12         if (i%pri[j]!=0)
    13             phi[i*pri[j]]=phi[i]*phi[pri[j]];
    14         else
    15         {
    16             phi[i*pri[j]]=phi[i]*pri[j];
    17             break;
    18         }
    19     }
    20 }
    (2)莫比乌斯函数

    题目:PC 1492

    积性证明: 
    [Math Processing Error]n=∏aipi,m=∏biqi,且[Math Processing Error]gcd(m,n)=1 
    ①若[Math Processing Error]∃pi>1或[Math Processing Error]qi>1,则[Math Processing Error]μ(n∗m)=μ(n)∗μ(m)=0 
    ②否则,[Math Processing Error]μ(n∗m)=(−1)n+m=μ(n)∗μ(m) 
    综上,[Math Processing Error]μ(n∗m)=μ(n)∗μ(m)

    写法: 
    ①素数m:[Math Processing Error]μ(m)=−1 
    ②m和比m的最小素因子小的素数n: 
    [Math Processing Error]μ(m∗n)=μ(m)∗μ(n) 
    ③m和m的最小素因子n:[Math Processing Error]μ(n∗m)=0

     1 mu[1]=vis[1]=1;
     2 for (int i=2;i<=n;i++)
     3 {
     4     if (!vis[i])
     5     {
     6         mu[i]=-1;
     7         pri[++tot]=i;
     8     }
     9     for (int j=1;j<=tot;j++)
    10     {
    11         if (i*pri[j]>n) break;
    12         vis[i*pri[j]]=1;
    13         if (i%pri[j]!=0)
    14             mu[i*pri[j]]=mu[i]*mu[pri[j]];
    15         else
    16         {
    17             mu[i*pri[j]]=0;
    18             break;
    19         }
    20     }
    21 }
    (3) 乘法逆元[Math Processing Error]inv(n,i)([Math Processing Error]n不变)

    题目:PC 1494

    积性证明: 
    [Math Processing Error]∵a∗inv[a]≡1,b∗inv[b]≡1(modn) 
    [Math Processing Error]∴(a∗b)∗(inv[a]∗inv[b])≡1(modn) 
    [Math Processing Error]∴inv[a∗b]≡inv[a]∗inv[b]

    写法: 
    ①素数m:根据费马小定理,[Math Processing Error]inv[m]≡Pow(m,n−2) 
    ②m和比m的最小素因子小的素数n:[Math Processing Error]inv[m∗n]=inv[m]∗inv[n] 
    ③m和m的最小质因子n: 
    根据完全积性,[Math Processing Error]inv[m∗n]=inv[m]∗inv[n]

    注意,第①步是[Math Processing Error]O(n)的。这是因为: 
    [Math Processing Error]O(π(n)log⁡n)=O(nln⁡nlog⁡n)=O(nlog⁡nlog⁡n)=O(n)。

     1 vis[1]=inv[1]=1;
     2 for (int i=2;i<n;i++)
     3 {
     4     if (!vis[i])
     5     {
     6         pri[++tot]=i;
     7         inv[i]=Pow(i,n-2);
     8     }
     9     for (int j=1;j<=tot;j++)
    10     {
    11         if (i*pri[j]>n) break;
    12         vis[i*pri[j]]=1;
    13         inv[i*pri[j]]=inv[i]*inv[pri[j]];
    14         if (i%pri[j]==0) break;
    15     }
    16 }

    其实可以直接有一种递推的方法: 
    ①当n=1时,inv[n]=1 
    ②假设当前对于k,已经求出了inv[1],inv[2],…,inv[k-1],当前要求出inv[k]。 
    [Math Processing Error]a=nmodk,[Math Processing Error]b=n/k 
    [Math Processing Error]∴n=a+b∗k 
    [Math Processing Error]∴a=n−b∗k 
    [Math Processing Error]∵inv[a]∗a≡inv[a]∗(n−b∗k)≡inv[a]∗−b∗k≡1 
    [Math Processing Error]∴inv[k]=−b∗inv[a]

    (4)最大公约数[Math Processing Error]gcd(a,b)(b一定)

    题目:PC 1495

    证明:略

    写法:求[Math Processing Error]g(i) 
    ①素数m:[Math Processing Error]g(m)=gcd(m,b); 
    ②m和比m的最小素因子小的素数n: 
    [Math Processing Error]g(m∗n)=g(m)∗g(n); 
    ③m和m的最小质因子n: 
    [Math Processing Error]ek(m)表示n的最大的幂,满足[Math Processing Error]ek(m)|m 
    [Math Processing Error](ek(m)∗n)|b,则[Math Processing Error]g(m∗n)=g(m)∗n 
    若不满足,则[Math Processing Error]g(m∗n)=g(m);

    [Math Processing Error]ek(i)不是积性函数,但也可以放在欧拉筛法里面求: 
    ①素数m:[Math Processing Error]ek(m)=m 
    ②m和比m的最小素因子小的素数n:[Math Processing Error]ek(m∗n)=n 
    ③m和m的最小质因子n:[Math Processing Error]ek(m∗n)=ek(m)∗n

    (5)正因子数目[Math Processing Error]d(n)

    题目:PC 1496

    证明: 
    [Math Processing Error]m=∏aipi,[Math Processing Error]n=∏biqi且[Math Processing Error]m,n互质 
    [Math Processing Error]∴d(mn)=d(∏aipi∏biqi)=∏(pi−1)∏(qi−1)=d(m)∗d(n)

    求法:求[Math Processing Error]d(i) 
    ①素数m:[Math Processing Error]d(m)=2 
    ②m和比m的最小素因子小的素数n:[Math Processing Error]d(m∗n)=d(m)∗d(n) 
    ③m和m的最小质因子n: 
    [Math Processing Error]d(m∗n)=d(m)/(e(m)+1)∗(e(m∗m)+1),[Math Processing Error]e(m)表示最大的满足[Math Processing Error]ne(m)|m的值。

    [Math Processing Error]e(i): 
    ①素数m:[Math Processing Error]e(m)=1 
    ②m和比m的最小素因子小的素数n:[Math Processing Error]e(m∗n)=1 
    ③m和m的最小质因子n:[Math Processing Error]e(m∗n)=e(m)+1

    (6)正因子之和[Math Processing Error]s(n)

    题目:PC 1497

    证明: 
    [Math Processing Error]m=∏aipi,[Math Processing Error]n=∏biqi且[Math Processing Error]m,n互质, 
    [Math Processing Error]s(m∗n)=∏j(∑j=0piaij)∗∏j(∑j=0qibij)=s(m)s(n)

    写法: 
    ①素数m:[Math Processing Error]s(m)=m+1 
    ②m和比m的最小素因子小的素数n:[Math Processing Error]s(m∗n)=s(m)∗s(n) 
    ③m和最小质因数n: 
    [Math Processing Error]s(m∗n)=s(∏aipi∗ne(i)+1)=∏(∑j=0piaij)∗(∑j=0e(i)+1nj)=s(m)∗(∑j=0e(i)+1nj)(∑j=0e(i)nj)=s(m)∗ne(i)+2−1n−1∗n−1ne(i)+1−1=s(m)∗ne(i)+2−1ne(i)+1−1

    [Math Processing Error]pe(m)=ne(i)+1,则可以在欧拉筛法的同时求出。

    (8)另一些显而易见的积性函数

    1(n):1(n)=1,完全积性 
    Id(n):Id(n)=n,完全积性 
    Idk(n):Idk(n)=n^k,完全积性

    3. 实现技巧

    (1)节省空间

    很多时候,有些数组A可以当作另外一些数组B的功能拓展,这时候就可以把B省略掉。

    例如,在求欧拉函数的时候,我们可以用phi来取代vis数组。因为没有求出来的phi(i)也就意味着i是素数。

    又例如,在求莫比乌斯函数的时候,我们可以用mu来取代vis数组。理由同上。不过要把mu数组的初始值设为-1。

    (2)模板

    变量:

    • 布尔数组vis[N]
    • 素数表pri[N],tot
    • 积性函数

    模板:

     1 void solve(void)
     2 {
     3     vis[1]=...=1;   //赋初始值 
     4     for (int i=2;i<=n;i++)
     5     {
     6         if (!vis[i])
     7         {
     8             ...             //素数的积性函数值
     9             pri[++tot]=i;   //加入素数表 
    10         }
    11         for (int j=1;j<=tot;j++)
    12         {
    13             if (i*pri[j]>n) break;
    14             vis[i*pri[j]]=1;
    15             ...                 //公共部分
    16             if (i%pri[j]!=0)
    17             {
    18                 ...             //m和比m的最小素因子小的素数n的处理 
    19             }
    20             else
    21             {
    22                 ...             //m和m的最小素因子n的处理 
    23                 break;
    24             }
    25         } 
    26     } 
    27 }

    4. 变式

    (1)“加性”函数

    例题:PC 1498 
    有些涉及到素因子的函数,也可以使用欧拉筛法求解。很多时候可以辅助积性函数的求解,上面的例子中的[Math Processing Error]e函数,[Math Processing Error]ek函数就是所谓的“加性”函数。

    (2)[Math Processing Error]A2

    例题:XSY 1001 
    对于[Math Processing Error]A2的积性函数,关键求出[Math Processing Error]A的积性函数,然后顺便求解[Math Processing Error]A2的积性函数。

    (3)[Math Processing Error](A+1)(A−1)

    例题:XSY 1001 
    通常一个乘积的形式,也可以通过互质的关系,转化为有关积性函数的问题。

  • 相关阅读:
    怎样理解 display:none 和 visibility:hidden
    怎样设置鼠标悬浮时弹出的文字提示框内容
    怎样获取当前元素节点的语言类型
    怎样控制元素节点的是否可拖动属性
    怎样读写分配给当前元素的快捷键
    怎样获取元素节点的标签名称
    怎样查看或修改元素节点的id属性
    怎样使用js将文本复制到系统粘贴板中
    怎样创建一个子树遍历器
    怎样创建一个子节点遍历器
  • 原文地址:https://www.cnblogs.com/luv-letters/p/9338355.html
Copyright © 2011-2022 走看看