莫比乌斯反演
莫比乌斯函数
定义: 将 (x) 质因子分解分解 (x=p_{1}^{d_{1}}p_{2}^{d_{2}}p_{3}^{d_{3}}···p_{k}^{d_{k}}).
莫比乌斯函数筛法:
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;//i*pri[j]里至少包含两个pri[j]
break;
}
Mobius[i*pri[j]]=-Mobius[i];//积性函数直接乘
}
}
}
性质1: 定义 (S(x)=sum_{dmid n}^{}mu (d)),则有:
证明:
(n=1) 时,结论显然成立。
(n=p_{1}^{alpha_{1}}p_{2}^{alpha_{2}}p_{3}^{alpha_{3}}···p_{k}^{alpha_{k}}) , 在 (n>1) 时,(kge 1).
对于任意约数(d=p_{1}^{eta_{1}}p_{2}^{eta_{2}}p_{3}^{eta_{3}}···p_{k}^{eta_{k}}) , (0leeta_{i}lealpha_{i}).
若存在 (eta_{i}ge 2) , 则有 (mu(d)=0).
那么,若要使 (mu(d)) 对 (S(n)) 产生影响 , 则需满足 (forall eta_{i}in[0,1])
故, (mu(d)) 的取值取决于 (eta_{i}=1) 的数量, 容易得到:
由二项式定理可知:
将 (a=-1 , b=1) 代入得:
证毕.
莫比乌斯反演
第一种形式
定义在正整数域的两个函数 (F(n)) 和 (f(n)) , 若 (F(n)=sum_{dmid n}^{}f(d)) ,
则 (f(n)=sum_{dmid n}{}mu (d)F(frac{n}{d})).
证明:
证毕.
第二种形式
若 (F(n)=sum_{n mid d}{}f(d)) , 则 (f(n)=sum_{nmid d}{} mu (frac{d}{n})F(d)).
证明:
证毕.
题解:设
则有
由莫比乌斯反演定律可知:
等式右边 (lfloorfrac{a'}{d'} floorlfloorfrac{b'}{d'} floor) 可用整除分块计算。
#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()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
sieve(50005);
t=qr();
while(t--)
{
a=qr();b=qr();c=qr();d=qr();k=qr();
printf("%lld
",f(b,d)-f(a-1,d)-f(b,c-1)+f(a-1,c-1));
}
//system("pause");
return 0;
}