【数论专题】——推式子

◇◆丶佛笑我妖孽 提交于 2019-11-27 22:09:32

今天主要就是推式子。

数论函数专题。

本文会参考大量资料(或者说照搬),会注明资料来源。

https://oi-wiki.org/(定义和证明等)


前置知识:

积性函数:形如

,则称

为积性函数。

几个必备积性函数:

  • 欧拉函数:

  

  • 莫比乌斯函数:

  

 

  • 恒等函数:

  

,其中

通常记为

  • 单位函数:

  


  • 除数函数:

  

 

通常记做d(n)。

  • 常数函数:

  

几个结论:

    

      


     (推导使用):

    

    

Dirichlet卷积:对于两个数论函数f,g,两者的Dirichlet卷积为:

一些基本的卷积式子:

(图源OIwiki)

 这些式子对化简题目有极大作用。

   既然是推式子,直接从一道例题入手:

  求:

  

  如果考虑朴素做法,对于n太大的情况无从下手,那么我们来简化式子。

  我们考虑引入莫比乌斯函数:

  我们枚举(i,j)的大小:

  

    式子内同除以d,得到:

    

   引入莫比乌斯函数:

   

   将枚举顺序变换,同第一步,先枚举(i,j),就可以把第四个sigma放到前面:

   

   后面两个求和因为贡献是1,因此直接写成平方形式:

   

    这里其实就可以直接数论分块写了,但还可以继续推:

  令

,枚举T的大小,并用Dirichlet卷积搞一搞:

  

    

    我们把phi用线性筛整出来,很容易就得到答案了。

来一道练手题:

 

P3327 [SDOI2015]约数个数和

最后用数论分块等东西搞搞就行了。

补充一个筛mu函数的模板:

 1 int vis[N],prime[N],mu[N],cnt;   2 void mu_sieve(){   3     mu[1]=1;   4     for(int i=2;i<=N;i++){   5         if(!vis[i]){   6             prime[++cnt]=i;   7             mu[i]=-1;   8         }   9         for(int j=1;j<=cnt;j++){  10             if(i*prime[j]>N) break;  11             vis[i*prime[j]]=1;  12             if(i%prime[j]==0){  13                 mu[i*prime[j]]=0;  14                 break;  15             }  16             else mu[i*prime[j]]=-mu[i];  17         }  18     }  19 }

在本题中,还需要筛出1~n的每个数约数个数和,可以看一下这位大佬的博客:GO

在线性筛基础上改造即可。

 1 #include<bits/stdc++.h>   2 using namespace std;   3 const int N=5e4+10;   4 int t,n,m;   5 int vis[N],prime[N],mu[N],d[N],num[N],cnt;   6 //vis 标记 prime 素数 mu 莫比乌斯函数 d 约数个数 num 最小质因子个数    7 void sieve(){   8     vis[1]=d[1]=mu[1]=1;   9     for(int i=2;i<=N;i++){  10         if(!vis[i]){  11             prime[++cnt]=i;  12             num[i]=1;  13             d[i]=2;  14             mu[i]=-1;  15         }  16         for(int j=1;j<=cnt&&i*prime[j]<=N;j++){  17             vis[i*prime[j]]=1;  18             if(i%prime[j]==0){  19                 mu[i*prime[j]]=0;  20                 d[i*prime[j]]=d[i]/(num[i]+1)*(num[i]+2);  21                 num[i*prime[j]]=num[i]+1;  22                 break;  23             }  24             else{  25                 d[i*prime[j]]=d[i]*d[prime[j]];  26                 num[i*prime[j]]=1;  27                 mu[i*prime[j]]=-mu[i];  28             }   29         }  30     }  31     for(int i=1;i<=N;i++){  32         mu[i]+=mu[i-1];  33         d[i]+=d[i-1];  34     }  35       36 }  37 int main(){  38     sieve();  39     scanf("%d",&t);  40     for(int k=1;k<=t;k++){  41         scanf("%d%d",&n,&m);  42         if(n>m) swap(n,m);  43         long long ans=0;  44         int i=1,j;  45         while(i<=n){  46             j=min(n/(n/i),m/(m/i));  47             ans+=1ll*(mu[j]-mu[i-1])*d[n/i]*d[m/i];  48             i=j+1;  49         }  50         printf("%lld\n",ans);  51     }  52     return 0;  53 }

 

 


 下面讲各种筛,continue……

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!