莫比乌斯反演
莫比乌斯函数
定义: 将 x 质因子分解分解 x=p1d1p2d2p3d3⋅⋅⋅pkdk.
μ(x)=⎩⎨⎧01(−1)k∃ di≥2x=1
莫比乌斯函数筛法:
int pri[N],vis[N],Mobius[N],tot;
void sieve_Mobius(int x)
{
vis[1]=Mobius[1]=1;
for(register int i=2;i<=x;i++)
{
if(!vis[i])
{
pri[++tot]=i;
Mobius[i]=-1;
}
for(register int j=1;j<=tot&&i*pri[j]<=x;j++)
{
vis[i*pri[j]]=1;
if(!(i%pri[j]))
{
Mobius[i*pri[j]]=0;
break;
}
Mobius[i*pri[j]]=-Mobius[i];
}
}
}
性质1: 定义 S(x)=∑d∣nμ(d),则有:
S(n)={1 n=10 n>1
证明:
n=1 时,结论显然成立。
n=p1α1p2α2p3α3⋅⋅⋅pkαk , 在 n>1 时,k≥1.
对于任意约数d=p1β1p2β2p3β3⋅⋅⋅pkβk , 0≤βi≤αi.
若存在 βi≥2 , 则有 μ(d)=0.
那么,若要使 μ(d) 对 S(n) 产生影响 , 则需满足 ∀βi∈[0,1]
故, μ(d) 的取值取决于 βi=1 的数量, 容易得到:
S(n)=∑i=0k(ik)(−1)i
由二项式定理可知:
(a+b)k=∑i=0k(ik)aibk−i
将 a=−1 , b=1 代入得:
0k=∑i=0k(ik)(−1)i=S(n)
证毕.
莫比乌斯反演
第一种形式
定义在正整数域的两个函数 F(n) 和 f(n) , 若 F(n)=∑d∣nf(d) ,
则 f(n)=∑d∣nμ(d)F(dn).
证明:
d∣n∑μ(d)F(dn)=d∣n∑μ(d)i∣dn∑f(i)=i∣n∑f(i)d∣in∑μ(d)=i∣n∑f(i)S(in) 由上文可知,仅当i=n时S(in)=1,否则S(in)=0=f(n)
证毕.
第二种形式
若 F(n)=∑n∣df(d) , 则 f(n)=∑n∣dμ(nd)F(d).
证明:
n∣d∑μ(nd)F(d)=n∣d∑μ(nd)d∣i∑f(i)=n∣i∑d′∣ni∑μ(d′) 设d′=nd=n∣i∑S(ni)=f(n)
证毕.
problem b
题解:设
F(k)=∑x=1a∑y=1b[k∣(x,y)]=⌊ka⌋⌊kb⌋ f(k)=∑x=1a∑y=1b[k=(x,y)]
则有
F(k)=∑k∣df(d)
由莫比乌斯反演定律可知:
f(k)=k∣d∑μ(kd)F(d)=k∣d∑μ(kd)⌊da⌋⌊db⌋=d′∑μ(d′)⌊d′a′⌋⌊d′b′⌋ 设d′=kd,a′=ka,b′=kb.
等式右边 ⌊d′a′⌋⌊d′b′⌋ 可用整除分块计算。
#include<bits/stdc++.h>
#define N 100005
#define LL long long
using namespace std;
int t;
LL a,b,c,d,k;
inline int qr()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int pri[N],vis[N],mobius[N],sum[N],tot;
void sieve(int x)
{
mobius[1]=vis[1]=1;
for(register int i=2;i<=x;i++)
{
if(!vis[i])
{
pri[++tot]=i;
mobius[i]=-1;
}
for(register int j=1;j<=tot&&i*pri[j]<=x;j++)
{
vis[i*pri[j]]=1;
if(!(i%pri[j]))
{
mobius[i*pri[j]]=0;
break;
}
mobius[i*pri[j]]=-mobius[i];
}
}
for(register int i=1;i<=x;i++)
sum[i]=sum[i-1]+mobius[i];
}
inline LL f(int a,int b)
{
LL res=0;
a=a/k,b=b/k;
int n=min(a,b);
int l=1,r=0;
while(l<=n)
{
r=min(n,min(a/(a/l),b/(b/l)));
res+=(LL)(sum[r]-sum[l-1])*(a/l)*(b/l);
l=r+1;
}
return res;
}
int main()
{
sieve(50005);
t=qr();
while(t--)
{
a=qr();b=qr();c=qr();d=qr();k=qr();
printf("%lld\n",f(b,d)-f(a-1,d)-f(b,c-1)+f(a-1,c-1));
}
return 0;
}