zoukankan      html  css  js  c++  java
  • [模板][P3377]杜教筛

    Description:

    求 $ sum_{i=1}^n phi(i) ,sum_{i=1}^n mu(i)$

    Hint:

    (n<=10^{10}​)

    Solution:

    考虑积性函数 (f,g,h​) 及其前缀和 (F,G,H​)

    其中 (h=f*g​)

    首先 (H(x)=sum_{n=1}^xh(n))

    (=sum_{n=1}^x sum_{d|n} f(d) g(frac{n}{d}))

    枚举倍数转枚举因数

    (=sum_{k=1}^x sum_{d=1}^{lfloor frac{x}{k} floor} f(d) g(k)​)

    $=sum_{k=1}^x g(k)sum_{d=1}^{lfloor frac{x}{k} floor} f(d) $

    (=sum_{k=1}^x g(k) F(lfloor frac{x}{k} floor))

    (=sum_{k=1}^{x}g(k)F(lfloor frac{x}{k} floor))

    (g(1)F(n)=H(n)-sum_{d=2}^{n}g(d)F(lfloor frac{n}{d} floor))

    此式是杜教筛的核心式,适用于非线性求一个积性函数的前缀和

    只要能快速求出 (H(n),sum g(d)) 就能在$ O(n^{ frac{2}{3}} ) $ 求出(F(n))

    (sum_{i=1}^n phi(i)=frac{n(n+1)}{2}-sum_{i=2}^n phi(lfloor frac{n}{i} floor))

    (sum_{i=1}^n mu(i)=1-sum_{i=2}^n mu(lfloor frac{n}{i} floor))

    先筛出线性数据范围内的,再杜教筛

    递归求解即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int mxn=5e6+5,inf=2147483647;
    int T,n,tot;
    int p[mxn],vis[mxn];
    ll mu[mxn],ph[mxn];
    map<int ,ll > smu,sph;
    
    void init()
    {
        vis[1]=mu[1]=ph[1]=1;
        for(int i=2;i<=mxn;++i) {
            if(!vis[i]) mu[i]=-1,ph[i]=i-1,p[++tot]=i;
            for(int j=1;j<=tot&&p[j]*i<=mxn;++j) {
                vis[p[j]*i]=1;
                if(i%p[j]) mu[p[j]*i]=-mu[i],ph[p[j]*i]=ph[p[j]]*ph[i];
                else {ph[p[j]*i]=ph[i]*p[j];break;}
            }
        }
        for(int i=2;i<=mxn;++i) mu[i]+=mu[i-1],ph[i]+=ph[i-1];
    }
    
    ll get_mu(int n)
    {
        if(n<=mxn) return mu[n];
        if(smu[n]) return smu[n]; ll ans=0;
        for(int l=2,r;r<inf&&l<=n;l=r+1) 
            r=n/(n/l),ans+=(r-l+1)*get_mu(n/l);
        return smu[n]=1ll-ans;	
    }
    
    ll get_ph(int n)
    {
        if(n<=mxn) return ph[n];
        if(sph[n]) return sph[n]; ll ans=0;
        for(int l=2,r;r<inf&&l<=n;l=r+1)  //一定是从2开始
            r=n/(n/l),ans+=(r-l+1)*get_ph(n/l);
        return sph[n]=(ull)n*(n+1ll)/2-ans;	
    }
    
    int main()
    {
        cin>>T; init();
        while(T--) {
            scanf("%d",&n);
            printf("%lld %lld
    ",get_ph(n),get_mu(n));
        }
        return 0;
    }
    
  • 相关阅读:
    关于HTML5画布canvas的功能
    HTML5新标签介绍
    为HTML5添加新样式标签
    iOS开发相关图书推荐
    Android相关图书推荐
    C语言相关图书推荐
    C#相关图书推荐
    C++相关图书推荐
    JavaScript相关图书推荐
    Java相关书籍推荐
  • 原文地址:https://www.cnblogs.com/list1/p/10395182.html
Copyright © 2011-2022 走看看