Given a positive integers nnn , Mobius function μ ( n ) \mu(n) μ(n) is defined as follows:
μ ( n ) = { 1 n = 1 ( − 1 ) k n = p 1 p 2 ⋯ p k 0 o t h e r \mu(n) = \begin{cases} 1 &n = 1 \\ (-1)^k & n = p_1p_2\cdots p_k \\ 0 &other \end{cases} μ(n)=⎩⎪⎨⎪⎧1(−1)k0n=1n=p1p2⋯pkother
p i ( i = 1 , 2 , ⋯ , k ) p i ( i = 1 , 2 , ⋯   , k ) pi(i=1,2,⋯,k)p_i (i = 1, 2, \cdots, k) pi(i=1,2,⋯,k)pi(i=1,2,⋯,k)are different prime numbers.
Given two integers mmm, nnn, please calculate ∑ i = 1 m μ ( i n ) \sum_{i = 1}^{m}\mu(in) ∑i=1mμ(in) .
Input
One line includes two integers m(1≤m≤2e9)m (1 \le m \le 2e9)m(1≤m≤2e9), n(1≤n≤1e12)n (1 \le n \le 1e12)n(1≤n≤1e12) .
Output
One line includes the answer .
样例输入 复制
2 2
样例输出 复制
-1
题意
给你n和m求解 ∑ i = 1 m μ ( i n ) \sum_{i=1}^m\mu(in) i=1∑mμ(in)其中 μ \mu μ为莫比乌斯函数
思路
先考虑n为含有平方因子的情况会发现,每一个i*n之后
μ
(
i
n
)
\mu(in)
μ(in)都会为0,所以特判一下
再考虑n不含有平方因子,那么n一定可以拆成
n
=
p
1
p
2
p
3
p
4
⋯
p
i
n=p_1p_2p_3p_4\cdots p_i
n=p1p2p3p4⋯pi
我们令
S
(
m
,
n
)
=
∑
i
=
1
m
μ
(
i
n
)
S(m,n)=\sum_{i=1}^m\mu(in)
S(m,n)=i=1∑mμ(in)然后现在考虑
n
n
n的一个素因子
d
d
d,
d
d
d可以是
n
n
n的任意一个素因子,那么肯定有
n
d
\frac{n}{d}
dn和
d
d
d互质,我们将n分解
∑
i
=
1
m
μ
(
i
n
)
=
∑
i
=
1
m
μ
(
i
⋅
n
d
⋅
d
)
\sum_{i=1}^m\mu(in)=\sum_{i=1}^m\mu\left ( i\cdot \frac{n}{d}\cdot d \right )
i=1∑mμ(in)=i=1∑mμ(i⋅dn⋅d)
其中
d
d
d和
n
d
\frac{n}{d}
dn一定是互质的,那么剩下就是考虑
d
d
d和
i
i
i的关系
[
1
,
m
]
[1,m]
[1,m]中的数和
d
d
d只会有两种可能互质和不互质的,由于
μ
(
)
\mu()
μ()为积性函数,那么若
i
i
i与
d
d
d互质就会有
μ
(
i
⋅
n
d
⋅
d
)
=
μ
(
i
⋅
n
d
)
μ
(
d
)
\mu\left ( i\cdot \frac{n}{d}\cdot d \right )=\mu\left ( i\cdot \frac{n}{d} \right )\mu\left (d \right )
μ(i⋅dn⋅d)=μ(i⋅dn)μ(d)
∑
i
=
1
m
μ
(
i
⋅
n
d
⋅
d
)
\sum_{i=1}^m\mu\left ( i\cdot \frac{n}{d}\cdot d \right )
i=1∑mμ(i⋅dn⋅d)
∑
i
=
1
m
μ
(
i
⋅
n
d
)
μ
(
d
)
=
−
∑
i
=
1
m
μ
(
i
⋅
n
d
)
\sum_{i=1}^m\mu\left ( i\cdot \frac{n}{d} \right )\mu\left (d \right )=-\sum_{i=1}^m\mu\left ( i\cdot \frac{n}{d} \right )
i=1∑mμ(i⋅dn)μ(d)=−i=1∑mμ(i⋅dn)
由于
μ
(
d
)
\mu(d)
μ(d)为单素数他的值肯定为
−
1
-1
−1,思考这个式子与原式的关系,会发现实际上多减了一个
i
i
i与
d
d
d不互质的部分,那我们给他加回去
i
i
i与
d
d
d不互质的部分就可以了,那现在考虑一下
[
1
,
m
]
[1,m]
[1,m]中与素数
d
d
d不互质的数是那些,就是
[
1
,
m
]
[1,m]
[1,m]中
d
d
d的倍数,只要从1枚举到
m
d
\frac{m}{d}
dm就可以了
∑
i
=
1
m
d
μ
(
i
⋅
d
⋅
n
d
)
=
∑
i
=
1
m
d
μ
(
i
n
)
\sum_{i=1}^{\frac{m}{d}}\mu(i\cdot d\cdot \frac{n}{d})=\sum_{i=1}^{\frac{m}{d}}\mu(in)
i=1∑dmμ(i⋅d⋅dn)=i=1∑dmμ(in)就好了,总结一下就是
∑
i
=
1
m
μ
(
i
n
)
=
−
∑
i
=
1
m
μ
(
i
⋅
n
d
)
+
∑
i
=
1
m
d
μ
(
i
n
)
\sum_{i=1}^m\mu(in)=-\sum_{i=1}^m\mu\left ( i\cdot \frac{n}{d} \right )+\sum_{i=1}^{\frac{m}{d}}\mu(in)
i=1∑mμ(in)=−i=1∑mμ(i⋅dn)+i=1∑dmμ(in)
也就是
S
(
m
,
n
)
=
−
S
(
m
,
n
d
)
+
S
(
m
d
,
n
)
S(m,n)=-S(m,\frac{n}{d})+S(\frac{m}{d},n)
S(m,n)=−S(m,dn)+S(dm,n)
有了这个递归方程,我们每次只要找到当前的n的一个素因子就可以递归下去了,递归到
S
(
0
,
n
)
=
0
和
S
(
m
,
1
)
S(0,n)=0和S(m,1)
S(0,n)=0和S(m,1)
S
(
m
,
1
)
=
∑
i
=
1
m
μ
(
i
)
S(m,1)=\sum_{i=1}^m\mu(i)
S(m,1)=i=1∑mμ(i)
由于m还是比较大,所以我们得用杜教筛来求莫比乌斯函数的前缀和,杜教筛可以在
O
(
n
2
3
)
O(n^{\frac{2}{3}})
O(n32)求出前缀和
这类积性函数的n倍(n为非平方因子数)求和的都有类似的式子若
f
(
i
)
f(i)
f(i)为积性函数则有
∑
i
=
1
m
f
(
i
n
)
=
f
(
d
)
∑
i
=
1
m
f
(
i
⋅
n
d
)
+
∑
i
=
1
m
d
f
(
i
n
)
\sum_{i=1}^mf(in)=f(d)\sum_{i=1}^mf\left ( i\cdot \frac{n}{d} \right )+\sum_{i=1}^{\frac{m}{d}}f(in)
i=1∑mf(in)=f(d)i=1∑mf(i⋅dn)+i=1∑dmf(in)
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
const int maxn=10000000;
long long prime[1000000],num;
int vst[maxn+5],miu[maxn+5],mu_n;
inline void Pre()
{
miu[1]=1;
for (int i=2; i<=maxn; i++)
{
if (!vst[i]) prime[++num]=i,miu[i]=-1;
for (int j=1; j<=num && (ll)i*prime[j]<=maxn; j++)
{
vst[i*prime[j]]=1;
if (i%prime[j]==0)
{
miu[i*prime[j]]=0;
break;
}
miu[i*prime[j]]=miu[i]*miu[prime[j]];
}
}
for (int i=1; i<=maxn; i++) miu[i]+=miu[i-1];
}
unordered_map<ll,int> S;
inline int Sum(ll n)
{
if (n<=maxn) return miu[n];
if (S.find(n)!=S.end()) return S[n];
int tem=1;
ll l,r;
for (l=2; l*l<=n; l++) tem-=Sum(n/l);
for (ll t=n/l; l<=n; l=r+1,t--)
{
r=n/t;
tem-=(r-l+1)*Sum(t);
}
return S[n]=tem;
}
long long f(long long m,long long n)
{
if(m==0) return 0;
if(n==1) return Sum(m);
int flag=1;
for(int i=1; prime[i]*prime[i]<=n; i++)
{
if(n%prime[i]==0)
{
flag=0;
return -f(m,n/prime[i])+f(m/prime[i],n);
}
}
if(flag)
{
return -f(m,n/n)+f(m/n,n);
}
}
int judge(long long n)
{
for(int i=1; prime[i]*prime[i]<=n; i++)
{
if(n%prime[i]==0)
{
int cnt=0;
while(n%prime[i]==0)
{
n/=prime[i];
cnt++;
}
if(cnt>=2)
{
return 0;
}
}
}
return 1;
}
int main()
{
Pre();
long long m,n;
scanf("%lld%lld",&m,&n);
if(!judge(n))
{
printf("0\n");
return 0;
}
long long ans=f(m,n);
printf("%lld\n",ans);
return 0;
}