莫比乌斯函数与杜教筛

前人的文章已经很详尽了,这里只作一点补充。

莫比乌斯反演与莫比乌斯函数入门资料:https://wenku.baidu.com/view/fbec9c63ba1aa8114431d9ac.html

讲的非常清楚,这里稍微补充一下:

1.虽然考试肯定不会考,但是对于定理的证明还是应该大概了解一下的。关于欧拉函数φ与莫比乌斯函数μ,由于它们都是积性函数,所以很多性质都可以用类似数学归纳法的方法证明。过程是:(1)对于一个性质证明在x为素数是成立 (2)对于素数p和一个正整数a,设此性质对a与p均成立,p*a成立。(3)由类似数学归纳法可知,对于全体正整数都满足性质。

2.事实上,莫比乌斯反演定理用处并不大,一般过程都会用它的“μ*I=e"性质代替。而φ*I=id的性质也经常使用。通常情况下这两个性质已经够应付大部分题目了。不过要明确所有变形的最终目的是使最终的式子可以“分块加速”:

LL solve(int n,int m){
    LL res=0;
    if (n>m) swap(n,m);
    for (int i=1,l=0; i<=n; i=l+1){
        l=min(n/(n/i),m/(m/i));
        res+=1ll*(sum[l]-sum[i-1])*(n/i)*(m/i);
    }
    return res;
} 

3.对于线性筛法(也就是欧拉筛,筛素数的同时可以预处理积性函数,还可以用来预处理其它一些东西)代码大概是这样:

void init(int n){
   memset(phi,-1,sizeof(phi));
   memset(miu,-1,sizeof(miu));
   int tot=0; miu[0]=phi[0]=0; miu[1]=phi[1]=1;
   rep(i,2,n){
      if (phi[i]==-1) p[++tot]=i,phi[i]=i-1,miu[i]=-1;
      for (int j=1; j<=tot && p[j]*i<=n; j++){
         if (i%p[j]) phi[i*p[j]]=phi[i]*(p[j]-1),miu[i*p[j]]=-miu[i];
         else { phi[i*p[j]]=phi[i]*p[j]; miu[i*p[j]]=0; break; }
      }
      phi[i]+=phi[i-1]; miu[i]+=miu[i-1];
   }
} 

然后就是习题:

https://www.cnblogs.com/Milkor/p/4474835.html

在草稿纸上把式子列出来就可以了,主要用来把变式练熟,翻来覆去本质上还是那两个性质和“枚举倍数”方法的应用。

不过杜教筛就没那么简单了,可以产生更多难度很高的题目。

首先要学会欧拉函数和莫比乌斯函数的前缀和求法。

http://blog.csdn.net/skywalkert/article/details/50500009

杜教筛目前最全的讲义之一,主要前面前缀和讲的很清楚。

注意存储方式,很巧妙的用线性大小的空间存储了结果(p放在n/p的位置上):

BZOJ3944(裸题)

#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std;

const int N=2000100,M=100100;
int cas,n,m,cnt,c[N];
ll phi[N],mu[N],p[M],q[M];
bool vis[M];

ll get_p(int x){ return (x<=m) ? phi[x] : p[n/x]; }
ll get_q(int x){ return (x<=m) ? mu[x] : q[n/x]; }

void solve(int x){
    if (x<=m) return;
    int i,j=1,t=n/x;
    if (vis[t]) return;
    vis[t]=1; p[t]=((ll)x+1)*x>>1; q[t]=1;
    while (j<x){
        i=j+1; j=x/(x/i); solve(x/i);
        p[t]-=get_p(x/i)*(j-i+1); q[t]-=get_q(x/i)*(j-i+1);
    }
}

int main(){
    scanf("%d",&cas); m=2000000;
    int i,j; phi[1]=mu[1]=1;
    for (i=2; i<=m; i++){
        if (!phi[i]) phi[i]=i-1,mu[i]=-1,c[++cnt]=i;
        for (j=1; j<=cnt && i*c[j]<=m; j++)
            if (i%c[j]) phi[i*c[j]]=phi[i]*(c[j]-1),mu[i*c[j]]=-mu[i];
            else{ phi[i*c[j]]=phi[i]*c[j]; mu[i*c[j]]=0; break; }
    }
    for (i=2; i<=m; i++) phi[i]+=phi[i-1],mu[i]+=mu[i-1];
    while (cas--){
        scanf("%d",&n); memset(vis,0,sizeof(vis));
        if (n<=m) printf("%lld %lld\n",phi[n],mu[n]);
            else solve(1ll*n),printf("%lld %lld\n",p[1],q[1]);
    }
    return 0;
}

练习可以用下面两题(相对于其它题目比较简单)

BZOJ4916:http://www.cnblogs.com/Troywar/p/8029537.html

NOI2016 D1 T3:https://www.cnblogs.com/lcf-2000/p/6250330.html

要说的也就这些了,刷题才是理解的最好方式。

原文地址:https://www.cnblogs.com/HocRiser/p/8207284.html

时间: 2024-08-27 01:10:09

莫比乌斯函数与杜教筛的相关文章

【51nod-1239&amp;1244】欧拉函数之和&amp;莫比乌斯函数之和 杜教筛

题目链接: 1239:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1239 1244:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1244 杜教筛裸题,不过现在我也只会筛这俩前缀和... $$s(n)=\sum _{i=1}^{n}f(i)$$ 那么就有: $$\sum_{i=1}^{n}f(i)\lfloor \frac{n}{i} \

【Luogu3768】简单的数学题(莫比乌斯反演,杜教筛)

[Luogu3768]简单的数学题(莫比乌斯反演,杜教筛) 题面 洛谷 \[求\sum_{i=1}^n\sum_{j=1}^nijgcd(i,j)\] $ n<=10^9$ 题解 很明显的把\(gcd\)提出来 \[\sum_{d=1}^nd\sum_{i=1}^n\sum_{j=1}^nij[gcd(i,j)==d]\] 习惯性的提出来 \[\sum_{d=1}^nd^3\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}ij[gcd(i,j)==1]\] 后面这玩意很明显的来一发

莫比乌斯反演 and 杜教筛总结

这几天做了几道和杜教筛有关的题目,赶紧记下来怕以后忘了 首先就是最常用的式子 对于一个函数f(x) 设$g(x) =\sum_{x|d}f(d)$ 则根据莫比乌斯反演有$$f(x) = \sum_{x|d}μ(\frac{d}{x})g(d)$$ 举一个最常见的例子 求$$\sum_{i=1}^{N}\sum_{j=1}^{M} [gcd(i, j) == 1]$$ 令$$g(x) =\sum_{i=1}^{N}\sum_{j=1}^{M} [x | gcd(i, j)]$$ 根据上面的公式有$

BZOJ4805: 欧拉函数求和(杜教筛)

4805: 欧拉函数求和 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 614  Solved: 342[Submit][Status][Discuss] Description 给出一个数字N,求sigma(phi(i)),1<=i<=N Input 正整数N.N<=2*10^9 Output 输出答案. Sample Input 10 Sample Output 32 HINT Source By FancyCoder 直接大力杜教筛

【bzoj 4176】 Lucas的数论 莫比乌斯反演(杜教筛)

Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数.他现在长大了,题目也变难了. 求如下表达式的值: 一行一个整数ans,表示答案模1000000007的值. Sample Input 2 Sample Output 8 HINT 对于100%的数据n <= 10^9. 题解: 解锁新技能:杜教筛. 再复习一下: 若$F(n)=\s

【BZOJ3944/4805】Sum/欧拉函数求和 杜教筛

[BZOJ3944]Sum Description Input 一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问 Output 一共T行,每行两个用空格分隔的数ans1,ans2 Sample Input 6 1 2 8 13 30 2333 Sample Output 1 1 2 0 22 -2 58 -3 278 -3 1655470 2 题解: 粘自http://blog.csdn.net/skywalkert/article/details/

莫比乌斯反演,杜教筛

BZOJ4176 #include <cstdio> #include <map> #define LL long long using namespace std; map <LL,LL> mpa; map <LL,LL> mpb; const LL mo=1e9+7; int b[10000001],phi[10000001],ss[10000001]; int miu[10000001],summiu[10000001],cnt,n; void eul

51nod1238 最小公倍数之和 V3 莫比乌斯函数 杜教筛

题意:求\(\sum_{i = 1}^{n}\sum_{j = 1}^{n}lcm(i, j)\). 题解:因为是用的莫比乌斯函数求的,所以推导比大部分题解多...而且我写式子一般都比较详细,所以可能看上去很多式子,实际上是因为每一步都写了,几乎没有跳过的.所以应该都可以看懂的. 末尾的\(e\)函数是指的\(e[1] = 1\),\(e[x] = 0(x != 1)\)这样一个函数 \[\sum_{i = 1}^{n}\sum_{j = 1}^{n}lcm(i, j)\] \[\sum_{i

数论入门——莫比乌斯函数,欧拉函数,狄利克雷卷积,线性筛,莫比乌斯反演,杜教筛

一个菜鸡对数论的一点点理解... 莫比乌斯函数 定义函数\(\mu(n)\)为: 当n有平方因子时,\(\mu(n)=0\). 当n没有平方因子时,\(\mu(n)=(-1)^{\omega(n)}\),\(\omega(n)\)表示n不同质因子的个数. 性质1: \(\sum_{d|n}\mu(d)=[n=1]\) 证明:我们把n分解质因数,则原式\(=(-1+1)^{\omega(n)}=0\). 因为对于不同的质因子,只有选和不选两种方案,这是一个组合数相加的形式,偶数加奇数减,根据二项式