• ACM-ICPC 2018 徐州赛区网络预赛 D. Easy Math


    Easy Math
    问答问题反馈
    •  16.47%
    •  1000ms
    • 262144K
     

    Given a positive integers nn , Mobius function mu(n)μ(n) is defined as follows:

    displaystyle mu(n) = egin{cases} 1 &n = 1 \ (-1)^k & n = p_1p_2cdots p_k \ 0 &other end{cases}μ(n)=1(1)k0n=1n=p1p2pkother

    p_i (i = 1, 2, cdots, k)pi(i=1,2,,k) are different prime numbers.

    Given two integers mm, nn, please calculate sum_{i = 1}^{m} mu(in)i=1mμ(in).

    Input

    One line includes two integers m (1 le m le 2e9)m(1m2e9), n (1 le n le 1e12)n(1n1e12).

    Output

    One line includes the answer .

    样例输入

    2 2

    样例输出

    -1

    题目来源

    ACM-ICPC 2018 徐州赛区网络预赛

    min_25筛的话,先得到下面这个公式

    首先答案可以化简为这个

    根据积性函数前缀和可以得到这个

    (Sf(m,1)+1)*mu(n)

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int N=1e6+5;
    ll p[N],w[N],pri[N],g[N],M,m,n;
    int block,id[N],sz,tot;
    bool is_p[N],v[N];
    void init(int n)
    {
        sz=0;
        for(int i=2; i<=n; i++)
        {
            if(!is_p[i])p[++sz]=i;
            for(int j=1; j<=sz&&p[j]*i<n; j++)
            {
                is_p[i*p[j]]=1;
                if(i%p[j]==0) break;
            }
        }
    }
    void sieve_g(ll n)
    {
        M=0;
        for(ll i=1,lst; i<=n; i=lst+1)
        {
            ll len=n/i;
            lst=n/len;
            w[++M]=len;
            g[M]=1-w[M];
            if(len<=block) id[len]=M;
        }
        for(int i=1; i<=sz; i++)
            for(int j=1; j<=M&&p[i]*p[i]<=w[j]; j++)
            {
                int op=w[j]/p[i]<=block?id[w[j]/p[i]]:n/(w[j]/p[i]);
                g[j]-=g[op]+i-1;
            }
    }
    ll S(ll x,ll y)
    {
        ll k,ans=0;
        if(x<=1||p[y]>x) return 0;
        if(x>block) k=m/x;
        else k=id[x];
        ans=g[k]+y-1;
        for(int i=1; i<=tot&&pri[i]<=w[k]; i++)
            if(pri[i]>p[y-1]) ans++;
        for(int i=y; i<=sz&&p[i]*p[i]<=x; i++)
            if(v[i]==0) ans-=S(x/p[i],i+1);
        return ans;
    }
    int main()
    {
        tot=0;
        cin>>m>>n;
        block=sqrt(m+0.5);
        init(m<=1e6?1e4:1e6);
        sieve_g(m);
        for(int i=1; p[i]*p[i]<=n&&i<=sz;i++)
        {
            if(n%p[i])continue;
            pri[++tot]=p[i];
            n/=p[i];
            v[i]=1;
            if(n%p[i]==0)
            {
                puts("0");
                return 0;
            }
        }
        if(n>1)
        {
            pri[++tot]=n;
            for(int i=sz; i>0; i--)
                if(p[i]==n)
                {
                    v[i]=1;
                    break;
                }
        }
        int t=tot&1?-1:1;
        cout<<(S(m,1)+1)*t;
        return 0;
    }

    莫比乌斯+杜教筛

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int N=1e6+5;
    int pri[N],num;
    int vst[N],mu[N],mu_n;
    inline void Pre()
    {
        mu[1]=1;
        for(int i=2; i<N; i++)
        {
            if(!vst[i]) pri[++num]=i,mu[i]=-1;
            for(int j=1; j<=num && i*1LL*pri[j]<N; j++)
            {
                vst[i*pri[j]]=1;
                if(i%pri[j]==0)
                {
                    mu[i*pri[j]]=0;
                    break;
                }
                mu[i*pri[j]]=mu[i]*mu[pri[j]];
            }
        }
        for(int i=1; i<N; i++) mu[i]+=mu[i-1];
    }
    unordered_map<ll,int> S;
    inline int Sum(ll n)
    {
        if(n<N) return mu[n];
        if(S.count(n)) 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;
    }
    ll f(ll m,ll n)
    {
        if(m==0) return 0;
        if(n==1) return Sum(m);
        int flag=1;
        for(int i=1; pri[i]*1LL*pri[i]<=n; i++)
        {
            if(n%pri[i]==0)
            {
                flag=0;
                return -f(m,n/pri[i])+f(m/pri[i],n);
            }
        }
        if(flag)return -f(m,n/n)+f(m/n,n);
    }
    int judge(ll n)
    {
        for(int i=1; pri[i]*1LL*pri[i]<=n; i++)
        {
            if(n%pri[i]==0)
            {
                int cnt=0;
                while(n%pri[i]==0)n/=pri[i],cnt++;
                if(cnt>=2)return 0;
            }
        }
        return 1;
    }
    int main()
    {
        Pre();
        ll m,n;
        cin>>m>>n;
        if(!judge(n))
        {
            printf("0
    ");
            return 0;
        }
        cout<<f(m,n);;
        return 0;
    }

     

  • 相关阅读:
    网上购物瘾,你怎么能退出?
    POJ 1006 Biorhythms 中国的法律来解决剩余的正式
    【Android接口实现】PhotoView——单点支持/多图像缩放,实现了触摸
    线程同步synchronized
    阿里云CentOS 6.5 设备、执行Docker容器和步骤的方法
    打破了中国电信华为无线路由猫(HG522-C)自己主动拨号+任意数量的计算机+iTV
    GCC 命令行具体解释
    Nginx 负载均衡
    Linux pipe功能
    Java有用的经验--Swing片
  • 原文地址:https://www.cnblogs.com/BobHuang/p/9702972.html
Copyright © 2020-2023  润新知