关于Mobius反演
欧拉函数 \(\varphi\)
\(\varphi(n)=\)表示不超过 \(n\) 且与 \(n\) 互质的正整数的个数
\[\varphi(n)=n\cdot \prod_{i=1}^{s}(1-\frac{1}{p_i})\]
其中 \(n = {p_1}^{\alpha1} \cdot {p_2}^{\alpha2} \cdots {p_s}^{\alpha s} \cdot\) 是 \(n\) 的标准分解。
由此易见 \(\text{euler}\) 函数是积性函数。
线性求 \(\text{euler}\) 函数:
#define int long long int phi[3000005]; int n=3000000; bool mark[3000005]; int prime[1000005]; int tot; void getphi() { phi[1]=1; for(int i=2;i<=n;i++) { if(mark[i]==false) { prime[++tot]=i; phi[i]=i-1; } for(int j=1;j<=tot;j++) { if(i*prime[j]>n) { break; } mark[i*prime[j]]=true; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } for(int i=1;i<=n;i++) { phi[i]+=phi[i-1]; } }
\(\text{mobius}\)函数 \(\mu(n)\)
\[ \mu(n)= \begin{cases} 1&n=1\\ 0&n\text{ 含有平方因子}\\ (-1)^k&k\text{ 为 }n\text{ 的本质不同质因子个数}\ \end{cases} \]
证明:
\[ \varepsilon(n)= \begin{cases} 1&n=1\\ 0&n\neq 1\ \end{cases} \]
其中 \(\displaystyle\varepsilon(n)=\sum_{d\mid n}\mu(d)\) 即 \(\varepsilon=\mu*1\)
设 \(\displaystyle n=\prod_{i=1}^k{p_i}^{c_i},n'=\prod_{i=1}^k p_i\)
那么 \(\displaystyle\sum_{d\mid n}\mu(d)=\sum_{d\mid n'}\mu(d)=\sum_{i=0}^k c_k^i\cdot(-1)^k\)
根据二项式定理,易知该式子的值在 \(k=0\) 即 \(n=1\) 时值为 \(1\) 否则为 \(0\) ,这也同时证明了 \(\displaystyle\sum_{d\mid n}\mu(d)=[n=1]\)
#define int long long int mu[3000005]; int n=3000000; bool mark[3000005]; int prime[1000005]; int tot; void getmu() { mu[1]=1; for(int i=2;i<=n;i++) { if(mark[i]==false) { prime[++tot]=i; mu[i]=-1; } for(int j=1;j<=tot;j++) { if(i*prime[j]>n) { break; } mark[i*prime[j]]=true; if(i%prime[j]==0) { mu[i*prime[j]]=0; break; } mu[i*prime[j]]=-mu[i]; } } }
\(\text{dirichlet}\)卷积
\(\text{id}:\text{id(i)=i}\)
\(\text{1}:\text{1(i)=1}\)
定义两个数论函数的\(\text{dirichlet}\)卷积为:
\[(f*g)(n)=\sum_{d|n}({f(d)\times g(\frac{n}{d})}) \]
性质:\(\text{dirichlet}\)卷积满足交换律和结合律。
单位元:\(\varepsilon\),\(\varepsilon(n)=[n==1]\),任何函数卷\(\varepsilon\)都为其本身.
\(1*\mu=\varepsilon\)
\(\mu * \text{id} = \varphi\)
\(1*\text{id}=\sigma\)
莫比乌斯反演
公式:设 \(f(n),g(n)\) 为两个数论函数。
如果有
\[ f(n)=\sum_{d\mid n}g(d) \]
那么有
\[ g(n)=\sum_{d\mid n}\mu(\frac{n}{d})f(d) \]
证明:
原命题等价于:已知 \(f=g*1\) ,证明 \(g=f*\mu\)
显然: \(f*\mu=g*1*\mu= g*\varepsilon=g\) (其中 \(1*\mu=\varepsilon\) )
同时,还有另一种\(\text{mobius}\)反演:
如果有
\[ f(n)=\sum_{n\mid d}g(d) \]
那么有
\[ g(n)=\sum_{n\mid d}\mu(\frac{d}{n})f(d) \]
整除分块
当遇到形如
\[\sum_{i=1}^{n}\lfloor \frac{n}{i} \rfloor\]
的柿子时。
可以采用\(o(\sqrt {n})\)复杂度的算法:整除分块
易证:对于部分连续的\(i\),\(\frac{n}{i}\)的值是相同的,考虑把它们合并计算,可以发现发现对于每一个值相同的块,它的最后一个数是n/(n/i)
。
简略证明:\(\frac{n}{i}\)就是所求的值,设为\(x\),那么可证对于值\(x\),它所在的块的最后一个数是\(\frac{n}{x}\)。
- 证明:反证法:对于数\(\frac{n}{x}+1\),它所在的块的值为\(\frac{n}{\frac{n}{x}+1}\),且\(\frac{n}{\frac{n}{x}+1}-x=\frac{x^2}{n+x}>0\)。$\therefore \(数\)\frac{n}{x}+1 \(和数\)\frac{n}{x}$不在同一个块中。
然后,原命题得证。
所以,易得计算原式方法。
for(int l=1,r;l<=n;l=r+1) { r=n/(n/l); ans+=(r-l+1)*(n/l); }
p2257 yy的gcd
设\(f(d)=\sum_{i=1}^{n}\sum_{i=1}^{m}[gcd(i,j)=d]\),
\(f(n)=\sum_{n\mid d}f(d)=\lfloor \frac{n}{n} \rfloor \times \lfloor \frac{m}{n} \rfloor\)
由莫比乌斯反演:\(f(n)=\sum_{n|d}\mu(\frac{d}{n})f(d)\)
\(ans=\sum_{i=1}^{n}\sum_{i=1}^{m}[gcd(i,j)=prim]\)
\(=\sum_{p\in prim}\sum_{i=1}^{n}\sum_{i=1}^{m}[gcd(i,j)=p]\)
\(=\sum_{p\in prim}f(p)\)
\(=\sum_{p\in prim}\sum_{p|d}\mu(\frac{d}{p})f(d)\)
改为枚举\(\frac{d}{p}\):
\(ans=\sum_{p\in prim}\sum_{i}^{min(\lfloor \frac{n}{p} \rfloor,\lfloor \frac{m}{p} \rfloor)}\mu(i)f(dp)\)
\(=\sum_{p\in prim}\sum_{d}^{min(\lfloor \frac{n}{p} \rfloor,\lfloor \frac{m}{p} \rfloor)}\mu(d) \times \lfloor \frac{n}{dp} \rfloor \times \lfloor \frac{m}{dp} \rfloor\)
设\(dp=t,t=p\)
\(ans=\sum_{t\in prim}\sum_{d}^{min(\lfloor \frac{n}{t} \rfloor,\lfloor \frac{m}{t} \rfloor)}\mu(\frac{t}{t}) \times \lfloor \frac{n}{t} \rfloor \times \lfloor \frac{m}{t} \rfloor\)
\(=\sum_{t=1}^{min(n,m)}\sum_{t\in prim,t|t}\mu(\frac{t}{t}) \times \lfloor \frac{n}{t} \rfloor \times \lfloor \frac{m}{t} \rfloor\)
\(=\sum_{t=1}^{min(n,m)}(\lfloor \frac{n}{t} \rfloor \times \lfloor \frac{m}{t} \rfloor) \times \sum_{t\in prim,t|t}\mu(\frac{t}{t})\)
代码:
//sum即为\(\sum_{t\in prim,t|t}\mu(\frac{t}{t})\)的前缀和
#include<bits/stdc++.h> using namespace std; #define ll long long int prime[10000005]; int mu[10000005]; ll f[10000005]; ll sum[10000005]; bool vis[10000005]; int cnt; void init() { mu[1]=1; for(int i=2;i<=10000000;i++) { if(vis[i]==false) { mu[i]=-1; prime[++cnt]=i; } for(int j=1;j<=cnt&&i*prime[j]<=10000000;j++) { vis[i*prime[j]]=true; if(i%prime[j]==0) { break; } mu[i*prime[j]]=-mu[i]; } } for(int i=1;i<=cnt;i++) { for(int j=1;j*prime[i]<=10000000;j++) { f[j*prime[i]]+=mu[j]; } } for(int i=1;i<=10000000;i++) { sum[i]=sum[i-1]+f[i]; } } ll solve(int a,int b)//运用整除分块 { ll ans=0; if(a>b) { swap(a,b); } for(int l=1,r=0;l<=a;l=r+1) { r=min(a/(a/l),b/(b/l)); ans+=(ll)(sum[r]-sum[l-1])*(a/l)*(b/l); } return ans; } signed main() { init(); int t; cin>>t; for(int i=1;i<=t;i++) { int a,b; scanf("%d %d",&a,&b); printf("%lld\n",solve(a,b)); } return 0; }