杜教筛

简介: 【6月更文挑战第9天】

以前学了些,后来也没用过,就搁置了,不会了,重新捡起来。决定写下来。参考罗老师的博客。

杜教筛 以及积性函数的前世今生 --算法竞赛专题解析(4)罗勇军的博客-CSDN博客积性函数在竞赛中

也可以参考唐老师的博客
浅谈一类积性函数的前缀和

杜教筛的核心

用途:

用于低于线性时间里,高效率求一些积性函数前缀和

算法:

说简单点就是整除分块+狄利克雷卷积+线性筛

公式:

$g(1)S(n)=\sum{i=1}^nh(i)-\sum{i=2}^ng(i)S([\frac{n}{i}])$

时间复杂度会缩小到$O(n^{\frac{2}{3}})$

积性函数

如果p和q互质并且$f(pq)=f(p)*f(q)$则称f是积性函数

如果对任意p和q都有$f(pq)=f(p)*f(q)$则成f是完全积性函数

常见的积性函数

  1. 除数函数 $\sigmak(n)=\sum {d|n} d^k$,表示n的约数的k次幂和,注意$\sigma _{k}(n)$与 $\sigma ^k(n)$是不同的 。

  2. 约数个数函数$\tau(n)=\sigma0(n) = \sum{d|n}$表示n的约数个数,一般也形成d(n)。

  3. 约数和函数$\sigma(n)=\sigma1(n)=\sum{d|n}d$,表示n的约数和。

  4. 欧拉函数$\varphi(n)=\sum{i=1}^n[(n,i)=1]\times1$表示不大于n切与n沪指的正整数个数,另外$\sum{i=1}^{n}[(n,i)=1]i=\frac{n\varphi(n)+[n=1]}{2}$且对于正整数n>2来说$\varphi(n)$是偶数。

  5. 莫比乌斯函数$\mu(n)$,在狄利克雷卷积的惩罚中与恒等函数互为逆元。$\mu(1)=1,$对于无平方的因子数,$n=\prod^t_{i=1}p_i$有$\mu(n)=(-1)^t$,对于有平方因子数有$\mu(n)=0$.

  6. 元函数$e(n)=[n=1]$,狄利克雷卷积的乘法单位元,完全积性

  7. 恒等函数$I(n)=1$完全积性

  8. 单位函数$id(n)=n$,完全积性

  9. 幂函数$id^k(n)=n^k,$完全积性

两个重要定理:

  1. $[n=1]=\sum_{d|n}\mu(d)$

  2. $n=\sum_{d|n}\varphi(d)$

整除分块:

自己以前写的:

https://blog.csdn.net/weixin_45911397/article/details/107870837

狄利克雷卷积

$(fg)(n)=h(n)$且f(n)和g(n)都是积性函数,那么$(fg)(n)=\sum_{d|n}f(d)*g(\frac{n}{d})$满足,交换律结合律,加法分配率

莫比乌斯反演:

自已以前写的:

https://blog.csdn.net/weixin_45911397/article/details/106079611

杜教筛

公式:

$g(1)S(n)=\sum{i=1}^{n}h(i)-\sum{i=2}^{n}g(i)s([\frac{n}{i}])$

推一个具体的式子:

$\sum_{i=1}^{n}\phi(i)$

这里我们就要使用性质了:$n=\sum_{d|n}\phi(d)$

$n=\phi(n)+\sum_{d|n ,d<n}\phi(d)$

$\phi(n)=n-\sum_{d|n,d<n}\phi(d)$

$\sum{i=1}^n\phi(i)=\sum{i=1}^n(i-\sum_{d|n,d<n}\phi(d))$

$\sum{i=1}^n\phi(i)=\frac{n*(n+1)}{2}-
\sum
{i=1}^n\sum_{d|n,d<n}\phi(d)$

枚举$\frac{i}{d}=d'$

$\sum{i=1}^n\phi(i)=\frac{n*(n+1)}{2}-
\sum
{d'=2}^{d'<=n}\sum_{d=1}^{d<=[\frac{n}{d'}]}\phi(d)$

令$S(n)=\sum_{i=1}^n\phi(i)$

$S(n)=\frac{n*(n+1)}{2}-\sum_{i=2}^nS(\frac{n}{i})$

//代码改写自:https://blog.csdn.net/KIKO_caoyue/article/details/100061406
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 5e6+7;         //超过n^(2/3),够大了

int prime[maxn];                //记录质数
bool vis[maxn];                 //记录是否被筛;
int mu[maxn];                   //莫比乌斯函数值
ll phi[maxn];                   //欧拉函数值
unordered_map<int,int> summu;   //莫比乌斯函数前缀和
unordered_map<int,ll> sumphi;   //欧拉函数前缀和
void init(){
                //线性筛预计算一部分答案
    int cnt = 0;
  vis[0] = vis[1] = 1;
  mu[1] = phi[1] = 1;
  for(int i=2;i<maxn;i++){
   
    if(!vis[i]){
   
            prime[cnt++] = i;
            mu[i] = -1;
            phi[i] = i-1;
        }
    for(int j=0;j<cnt && i*prime[j]<maxn;j++){
   
      vis[i*prime[j]] = 1;
      if(i%prime[j]){
   
        mu[i*prime[j]] = -mu[i];
        phi[i*prime[j]] = phi[i]*phi[prime[j]];
      }
      else{
   
        mu[i*prime[j]] = 0;
        phi[i*prime[j]] = phi[i]*prime[j];
        break;
      }
    }
  }
  for(int i=1;i<maxn;i++){
          //最后,mu[]和phi[]改为记录1~maxn的前缀和。
        mu[i] += mu[i-1];
        phi[i] += phi[i-1];
    }
}
int gsum(int x){
                // g(i)的前缀和
  return x;
}
ll getsmu(int x){
   
  if(x < maxn) return mu[x];      //预计算
  if(summu[x]) return summu[x];   //记忆化
  ll ans = 1;                    //杜教筛公式中的 1
  for(ll l=2,r;l<=x;l=r+1){
         //用整除分块计算杜教筛公式
    r = x/(x/l);
    ans -= (gsum(r)-gsum(l-1))*getsmu(x/l);
  }
  return summu[x] = ans/gsum(1);
}
ll getsphi(int x){
   
  if(x < maxn) return phi[x];
  if(sumphi[x]) return sumphi[x];  //记忆化,每个sumphi[x]只用算一次
  ll ans = x*((ll)x+1)/2;          //杜教筛公式中的 n(n+1)/2
  for(ll l=2,r;l<=x;l=r+1){
          //用整除分块计算杜教筛公式,这里算 sqrt(x)次
    r = x/(x/l);
    ans -= (gsum(r)-gsum(l-1))*getsphi(x/l);
  }
  return sumphi[x] = ans/gsum(1);
}
int main(){
   
  init();  //用线性筛预计算一部分
  int t;
  scanf("%d",&t);
  while(t--){
   
    int n;
    scanf("%d",&n);
    printf("%lld %lld\n",getsphi(n),getsmu(n));
  }
  return 0;
}
目录
相关文章
|
8月前
|
机器学习/深度学习 算法
【算法基础】筛质数
【算法基础】筛质数
37 0
|
8月前
|
C++
筛质数、分解质因数和快速幂的应用
筛质数、分解质因数和快速幂的应用
50 0
|
9月前
|
算法
初阶OI素数算法——埃拉托尼斯筛
时间复杂度比较优秀且易于理解的素数筛选法
50 0
|
2月前
|
算法 测试技术 C++
【数学归纳法 组合数学】容斥原理
【数学归纳法 组合数学】容斥原理
|
12月前
AcWing 868. 筛质数
AcWing 868. 筛质数
|
10月前
|
机器学习/深度学习
卡特兰数
卡特兰数
48 0
|
10月前
|
算法
数星星(树状数组模板题)
数星星(树状数组模板题)
30 0
|
存储
欧拉筛&&埃氏筛
欧拉筛&&埃氏筛
|
算法
质数筛法:朴素素数筛,埃氏筛,欧式筛
质数筛法:朴素素数筛,埃氏筛,欧式筛
108 0
|
算法
状态压缩DP
复习acwing算法基础课的内容,本篇为讲解基础算法:动态规划——状态压缩DP,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。
131 0
状态压缩DP