sum\(\mu\)求法


\[S(n)=\sum_{i=1}^n \mu(i)\]
回顾公式
\[\sum_{d|n}\mu(d)=[n=1]\]
对\(n\)求和
\[\sum_{i=1}^n\sum_{d|i}\mu(d)=1\]
换一种求和
\[\sum_{i=1}^n\sum_{d=1}^{\lfloor n/i \rfloor}\mu(d)=1\]
拆成两部分
\[\sum_{i=1}^n\mu(i)=1-\sum_{i=2}^n\sum_{d=1}^{\lfloor n/i \rfloor}\mu(d)\]
注意到右边遇到的都是子问题
\[S(n)=1-\sum_{i=2}^nS(\lfloor\frac{n}{i}\rfloor)\]
注意到连除有结合律
\[\lfloor\frac{\lfloor\frac{a}{b}\rfloor}{c}\rfloor=\lfloor\frac{a}{bc}\rfloor\]

时间复杂度

本质上只需要计算\(S(\lfloor\frac{n}{i}\rfloor)(1\leq i\leq n)\)。

大家都知道\(\lfloor\frac{n}{i}\rfloor\)本质不同的结果只有\(2\sqrt{n}\)个,整除分块的套路。

在已知\(S(\lfloor\frac{n}{i}\rfloor)(2\leq i\leq n)\)的情况下,计算\(S(n)\)的复杂度为\(O(\sqrt{n})\)。

所以总时间复杂度为
\[\sum_{i=1}^{\sqrt{n}}\sqrt{\frac{n}{i}}+\sum_{i=1}^{\sqrt{n}}\sqrt{i}\]
把求和换成积分的技巧,原式等于
\[\int_{0}^{\sqrt{n}}\sqrt{\frac{n}{x}}dx+\int_{0}^{\sqrt{n}}\sqrt{x}dx\]
不定积分的结果为
\[\int\sqrt{\frac{n}{x}}dx=2\sqrt{nx}\]
\[\int\sqrt{x}dx=\frac{2}{3}x^{\frac{3}{2}}\]
牛顿-莱布尼茨定理求出定积分\(=\frac{8}{3}n^{\frac{3}{4}}=O(n^{\frac{3}{4}})\)

引入参数\(B\),假设\(1,2,\dots,\frac{n}{B}\)用线性筛,其余部分用原办法,总复杂度为
\[\sum_{i=1}^B\sqrt{\frac{n}{i}}+\frac{n}{B}=2\sqrt{nB}+\frac{n}{B}\]
当\(B=O(n^{\frac{1}{3}})\)时,两部分相等,取到最小值,时间复杂度为\(O(n^{\frac{2}{3}})\)。

sum\(\varphi\)求法

同样的技巧可以用在欧拉函数上
\[\sum_{d|n}\varphi(n)=n\]
只是右侧求和要换成\(n(n+1)/2\)。

代码

借鉴@lazyzhong的代码,不过我都是用上述办法算的两个函数,没有嵌套

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
#include<complex>
#define rg register
#pragma GCC optimize ("O3")
using namespace std;
template<class T> inline T read(T&x){
    T data=0;
    int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXN=1700000; // 2147483647^{2/3}=1664510.6449518746191262425357001
int prime[MAXN],pcnt; // use prime as well as isprime
int mu[MAXN];
ll phi[MAXN];

inline void sieve()
{
    fill(prime,prime+MAXN,1);
    mu[1]=1,phi[1]=1,pcnt=0;
    for(rg int i=2;i<MAXN;++i)
    {
        if(prime[i])
        {
            prime[++pcnt]=i,mu[i]=-1,phi[i]=i-1;
        }
        for(rg int j=1;j<=pcnt&&i*prime[j]<MAXN;++j)
        {
            prime[i*prime[j]]=0;
            if(i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            mu[i*prime[j]]=-mu[i];
            phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
    for(rg int i=2;i<MAXN;++i)
        mu[i]+=mu[i-1],phi[i]+=phi[i-1];
}

map<int,ll>ans_mu;

ll cal_mu(int n)
{
    if(n<MAXN)
        return mu[n];
    if(ans_mu.count(n))
        return ans_mu[n];
    ll ans=1; // first positive 1
    for(rg int i=2,j;i<=n;i=j+1) // i should be long long because n max=INF,then i can be -1
    {
        j=n/(n/i),ans-=(j-i+1)*cal_mu(n/i);
    }
    return ans_mu[n]=ans;
}

map<int,ll>ans_phi;

ll cal_phi(int n)
{
    if(n<MAXN)
        return phi[n];
    if(ans_phi.count(n))
        return ans_phi[n];
    ll ans=(ll)n*(n+1)/2;
    for(rg int i=2,j;i<=n;i=j+1)
    {
        j=n/(n/i),ans-=(j-i+1)*cal_phi(n/i);
    }
    return ans_phi[n]=ans;
}

int main()
{
    sieve();
    int T;
    read(T);
    while(T--)
    {
        int n;
        read(n);
        printf("%lld %lld\n",cal_phi(n),cal_mu(n));
    }
    return 0;
}

Hint

AC记录

LG4213 【【模板】杜教筛(Sum)】的更多相关文章

  1. p4213 【模板】杜教筛(Sum)

    传送门 分析 我们知道 $\varphi * 1 = id$ $\mu * 1 = e$ 杜教筛即可 代码 #include<iostream> #include<cstdio> ...

  2. [模板] 杜教筛 && bzoj3944-Sum

    杜教筛 浅谈一类积性函数的前缀和 - skywalkert's space - CSDN博客 杜教筛可以在\(O(n^{\frac 23})\)的时间复杂度内利用卷积求出一些积性函数的前缀和. 算法 ...

  3. luoguP4213 [模板]杜教筛

    https://www.luogu.org/problemnew/show/P4213 同 bzoj3944 考虑用杜教筛求出莫比乌斯函数前缀和,第二问随便过,第一问用莫比乌斯反演来做,中间的整除分块 ...

  4. LG4213 【模板】杜教筛(Sum)和 BZOJ4916 神犇和蒟蒻

    P4213 [模板]杜教筛(Sum) 题目描述 给定一个正整数$N(N\le2^{31}-1)$ 求 $$ans_1=\sum_{i=1}^n\varphi(i)$$ $$ans_2=\sum_{i= ...

  5. 51NOD 1222 最小公倍数计数 [莫比乌斯反演 杜教筛]

    1222 最小公倍数计数 题意:求有多少数对\((a,b):a<b\)满足\(lcm(a,b) \in [1, n]\) \(n \le 10^{11}\) 卡内存! 枚举\(gcd, \fra ...

  6. BZOJ3944: Sum(杜教筛模板)

    BZOJ3944: Sum(杜教筛模板) 题面描述 传送门 题目分析 求\(\sum_{i=1}^{n}\mu(i)\)和\(\sum_{i=1}^{n}\varphi(i)\) 数据范围线性不可做. ...

  7. Luogu 4213 【模板】杜教筛(Sum)

    当作杜教筛的笔记吧. 杜教筛 要求一个积性函数$f(i)$的前缀和,现在这个东西并不是很好算,那么我们考虑让它卷上另外一个积性函数$g(i)$,使$(f * g)$的前缀和变得方便计算,然后再反推出这 ...

  8. [bzoj3944] sum [杜教筛模板]

    题面: 传送门 就是让你求$ \varphi\left(i\right) $以及$ \mu\left(i\right) $的前缀和 思路: 就是杜教筛的模板 我们把套路公式拿出来: $ g\left( ...

  9. luoguP4213 【模板】杜教筛(Sum)杜教筛

    链接 luogu 思路 为了做hdu来学杜教筛. 杜教筛模板题. 卡常数,我加了register居然跑到不到800ms. 太深了. 代码 // luogu-judger-enable-o2 #incl ...

  10. [洛谷P4213]【模板】杜教筛(Sum)

    题目大意:给你$n$,求:$$\sum\limits_{i=1}^n\varphi(i),\sum\limits_{i=1}^n\mu(i)$$最多$10$组数据,$n\leqslant2^{31}- ...

随机推荐

  1. sqlalchemy 模型中添加根据身份证号计算性别和年龄

    class Users(Base, BaseMixin): username = Column(String(24)) id_Num = Column(String(18) ) # 身份证号码 @pr ...

  2. 7.7 C++基本关联式容器

    参考:http://www.weixueyuan.net/view/6404.html 总结: 基本的关联式容器主要有:set.multiset.map和multimap,这四种容器可以分为两组:ma ...

  3. Linux如何从零开始搭建rsync服务器(centOS6)

    Step1:检查rsync是否已经安装 rmp -qa rsync 如果没有安装的话,通过yum install rsync -y   Step2:给rsync服务添加本地用户,用于管理本地目录. u ...

  4. <Yarn> <Capacity Scheduler> <Source Code>

    Yarn capacity scheduler 首先要知道, [Attention: RM有两个组件,其中Scheduler完全就只是负责资源的分配:ApplicationsManager则负责接受a ...

  5. fread 不能读取最后一个数据块

    今天遇到一个问题,fread()竟然不能读取文件中的最后一个数据块. 我定义了一个结构体: Persong { char name[10]; char phone[15]; } 以及两个函数: int ...

  6. 字符界面的贪吃蛇--链表--C++

    前天看了下链表,由于平时对链表的使用不多,所以对链表的应用也没什么了解,所以想来想去,就想用链表实现一下贪吃蛇. 下面言归正传,先看效果图,再看代码,其他没有了! 图1: 图2: 代码: #inclu ...

  7. web 架构 /http协议,状态码,django中常用命令

    什么是web应用? web应用 架构 :B/S架构 | C/S架构 网站:BS架构其实就是应用程序: B是浏览器 S是sever(实现了wsgi协议,实现了socket的服务端) + applicat ...

  8. 升级ChinaCock 10.3遇到的问题

    1.引用ChinaCockFMX.jar,无法编译 因为专家重新改了fmx.dex.jar中的内容,并集成到ChinaCockFMX.jar中,所以需要去掉fmx.dex.jar的引用. 2.导航无法 ...

  9. python sort、sorted高级排序技巧

    文章转载自:脚本之家 Python list内置sort()方法用来排序,也可以用python内置的全局sorted()方法来对可迭代的序列排序生成新的序列. 1)排序基础 简单的升序排序是非常容易的 ...

  10. render finished