卧薪尝胆,厚积薄发。
迷迷茫茫
Date: Wed Mar 06 15:59:27 CST 2019
In Category:
NoCategory
Description:
求:
$$
\sum_{n=L}^R\sum_{x=1}^n\sum_{y=1}^n[\text{lcm}(x,y)=n]
$$
$1\leqslant L\leqslant R\leqslant 10^{11}$
Solution:
先化式子:
$$
\begin{align}
&ans=\sum_{n=L}^Rf(n),f(n)=\sum_{x=1}^n\sum_{y=1}^n[\text{lcm}(x,y)=n]\\
&设g(n)=\sum_{x=1}^n\sum_{y=1}^n[\text{lcm}(x,y)|n]=\sum_{x=1}^n\sum_{y=1}^n[x|n][y|n]=\sigma_0^2(n)\\
&那么有:g(n)=\sum_{d|n}f(d)\\
&根据莫比乌斯反演定理:f(n)=\sum_{d|n}\mu(\frac n d)g(d)=\sum_{d|n}\mu(\frac n d)\sigma_0^2(d)\\
\end{align}
$$
然后我们要证明一个结论:
$$
\sum_{d|n}\mu(\frac nd)\sigma_0^2(d)=\sigma_0(n^2)
$$
假设上式成立,先莫比乌斯反演:
$$
\begin{align}
\sigma_0^2(n)&=\sum_{d|n}\sigma_0(d^2)\\
\prod_{i=1}^{k_n}(q_{n,i}+1)(q_{n,i}+1)&=\sum_{d|n}\prod_{i=1}^{k_n}(2q_{d,i}+1)\\
\prod_{i=1}^{k_n}(q_{n,i}+1)(q_{n,i}+1)&=\prod_{i=1}^{k_n}\sum_{j=0}^{q_{n,i}}(2j+1)\\
\prod_{i=1}^{k_n}(q_{n,i}^2+2q_{n,i}+1)&=\prod_{i=1}^{k_n}\frac{(2q_{n,i}+1+1)\times(q_{n,i}+1)}{2}\\
\end{align}
$$
所以我们要求的就是:
$$
\sum_{i=1}^n\sigma_0(n^2)
$$
考虑怎么把平方去掉:
$$
\begin{align}
\sigma_0(n^2)&=\prod_{i=1}^k(2q_i+1)\\
&=\sum_{S\subseteq \{1,2,\dots,k\}}2^{|S|}\prod_{i\in S}q_i\\
&=\sum_{d|n}2^{w(d)}
\end{align}
$$
$w(n)$
代表
$n$
的不同质因子数,
$2^{w(n)}$
也就是
$n$
的无平方因子数,那么有:
$$
2^{w(n)}=\sum_{d|n}\mu^2(d)
$$
设
$f(n)=\sigma_0(n^2),g(n)=2^{w(n)},h(n)=\mu^2(n)$
。
那么有:
$$
f(n)=1\times g(n),g(n)=1\times h(n),f(n)=h(n)\times 1\times1=h(n)\times \sigma_0(n)
$$
根据这个式子我们可以线性筛,具体来说:
$$
\begin{align}
f(xy)&=f(x)f(y)(\gcd(x,y)=1)\\
f(p)&=h(p)+\sigma_0(p)=1+2=3\\
f(p^c)&=\sum_{i=0}^ch(p^i)\sigma_0(p^{c-i})=h(1)\sigma_0(p^c)+h(p)\sigma_0(p^{c-1})=c+1+c=2c+1
\end{align}
$$
但是还不够:
$$
\sum_{i=1}^nf(i)=\sum_{i=1}^n\sum_{d|i}h(d)\sigma_0(\frac id)=\sum_{d=1}^n\mu^2(d)\sum_{k=1}^{\lfloor\frac n d\rfloor}\sigma_0(k)=\sum_{d=1}^n\mu^2(d)s(\lfloor\frac n d\rfloor)
$$
所以如果我们能计算出
$\sigma_0$
和
$\mu^2$
的前缀和就可以除法分块了。
$$
\sum_{i=1}^n\sigma_0(i)=\sum_{i=1}^n\lfloor\frac n i\rfloor
$$
于是
$\sigma_0$
可以除法分块。
由于
$\sum \mu^2(d)$
表示的是
$n$
以内无平方因子数,因此我们可以考虑容斥:
$$
\sum_{i=1}^{\sqrt n}\mu(i)\lfloor\frac n{i^2}\rfloor
$$
也就是枚举
$n$
的平方因子,可以发现容斥系数是莫比乌斯函数,这样所有平方因子都会被计算
$0$
次,而
$1$
会被计算一次。
但是这样显然复杂度还是不对,于是我们可以先线性筛预处理
$n^{\frac 2 3}$
的部分,然后后面的出发分块做就行了。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#include<cctype>
#include<cstring>
using namespace std;
#define MAXN 5000010
#define N 5000000
typedef long long ll;
int mindivc[MAXN];
int prime[MAXN],tot = 0;
bool isprime[MAXN];
int mu[MAXN],mus[MAXN];
ll sig[MAXN];
#define R register
#define I inline
I void init()
{
for(R int i = 2;i <= N;++i)isprime[i] = true;
sig[1] = mu[1] = mus[1] = 1;
for(R int i = 2;i <= N;++i)
{
if(isprime[i])prime[++tot] = i,mindivc[i] = 1,mu[i] = -1,sig[i] = 2;
for(R int j = 1;j <= tot && i * prime[j] <= N;++j)
{
R int k = i * prime[j];
isprime[k] = false;
if(i % prime[j] == 0)
{
mindivc[k] = mindivc[i] + 1;mu[k] = 0;
sig[k] = sig[i] / (mindivc[i] + 1) * (mindivc[i] + 2);
break;
}
else
{
mindivc[k] = 1;mu[k] = -mu[i];sig[k] = sig[i] * 2;
}
}
mus[i] = mus[i - 1] + abs(mu[i]);
sig[i] = sig[i - 1] + sig[i];
}
return;
}
I ll sigma(ll n)
{
if(n <= N)return sig[n];
R ll ans = 0;
for(R ll l = 1,r;l <= n;l = r + 1)
{
r = n / (n / l);
ans = ans + (r - l + 1) * (n / l);
}
return ans;
}
struct hash
{
#define MOD 1000007
int head[MOD];
ll state[MOD],val[MOD];
int nxt[MOD],tot;
hash(){memset(head,0,sizeof(head));tot = 0;}
I ll find(ll x)
{
R int mod = x % MOD;
for(R int i = head[mod];i != 0;i = nxt[i])if(state[i] == x)return val[i];
return -1;
}
I void set(ll p,ll v)
{
R int mod = p % MOD;
++tot;state[tot] = p;val[tot] = v;nxt[tot] = head[mod];head[mod] = tot;
return;
}
}smu;
I ll summu(ll n)
{
if(n <= N)return mus[n];
R ll val = smu.find(n);
if(val != -1)return val;
R ll ans = 0;
for(R ll i = 1;i * i <= n;++i)
{
ans += mu[i] * (n / (i * i));
}
smu.set(n,ans);
return ans;
}
I ll calc(ll n)
{
R ll ans = 0;
for(R ll l = 1,r;l <= n;l = r + 1)
{
r = n / (n / l);//if(r / 1000 != (l - 1) / 1000)cout << l << " " << r << endl;
ans = ans + (summu(r) - summu(l - 1)) * sigma(n / l);
}
return ans;
}
ll query(ll n)
{
if(n == 0)return 0;
return (calc(n) + n) / 2;
}
int main()
{
init();
ll l,r;scanf("%lld%lld",&l,&r);
cout << query(r) - query(l - 1) << endl;
return 0;
}
In tag:
数学-莫比乌斯反演
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡