ACM-ICPC 2018 徐州赛区网络预赛 D. Easy Math(递归式+杜教筛)

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=p1p2pkother

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=1mμ(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=p1p2p3p4pi
我们令 S ( m , n ) = ∑ i = 1 m μ ( i n ) S(m,n)=\sum_{i=1}^m\mu(in) S(m,n)=i=1mμ(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=1mμ(in)=i=1mμ(idnd)
其中 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 ) μ(idnd)=μ(idn)μ(d)
∑ i = 1 m μ ( i ⋅ n d ⋅ d ) \sum_{i=1}^m\mu\left ( i\cdot \frac{n}{d}\cdot d \right ) i=1mμ(idnd)
∑ 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=1mμ(idn)μ(d)=i=1mμ(idn)
由于 μ ( 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=1dmμ(iddn)=i=1dmμ(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=1mμ(in)=i=1mμ(idn)+i=1dmμ(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)=0S(m,1)
S ( m , 1 ) = ∑ i = 1 m μ ( i ) S(m,1)=\sum_{i=1}^m\mu(i) S(m,1)=i=1mμ(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=1mf(in)=f(d)i=1mf(idn)+i=1dmf(in)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
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 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;
}

你可能感兴趣的:(数论,素数筛)