首页 > 其他分享 >杜教筛入门

杜教筛入门

时间:2024-07-18 12:31:22浏览次数:9  
标签:lfloor le frac 入门 int sum rfloor 杜教

当学 Min 25 的一个前置知识。


算法内容。

定义 \(S(n)=\sum_{i=1}^nf(i)\)。对于一个函数 \(g\),有:

\[\begin{aligned} \sum_{i=1}^n(f\times g)(i)&=\sum_{i=1}^n\sum_{d|i}f(\frac{i}{d})g(d)\\ &=\sum_{d=1}^ng(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}f(i)\\ &=\sum_{d=1}^ng(d)S(\lfloor\frac{n}{d}\rfloor)\\ \implies g(1)S(n)&=\sum_{d=1}^ng(d)S(\lfloor\frac{n}{d}\rfloor)-\sum_{d=2}^ng(d)S(\lfloor\frac{n}{d}\rfloor)\\ \implies S(n)&=\frac{\sum_{d=1}^ng(d)S(\lfloor\frac{n}{d}\rfloor)-\sum_{d=2}^ng(d)S(\lfloor\frac{n}{d}\rfloor)}{g(1)} \end{aligned} \]

所以如果存在函数 \(g\),满足:

  1. \(g(1)\neq 0\)
  2. \(\sum_{i=1}^n(f\times g)(i)\) 可以快速计算
  3. \(g(i)\) 可以快速计算

可以通过记忆化搜索+数论分块快速计算 \(S(n)\)。可以用 unordered_map存储结果。

直接计算复杂度为 \(O(n^{\frac{3}{4}})\)。更好的计算是预处理前 \(O(n^{\frac{2}{3}})\) 的 \(S\) 值,可以做到 \(O(n^{\frac{2}{3}})\) 的复杂度。

具体证明可以参考 link。证明本质是积分,简单的。

常用构建函数 \(g\) 技巧:

  1. \(\sum_{d|n}^n\mu(d)=[n=1]\)
  2. \(\sum_{d|n}^nu(d)\frac{n}{d}=\varphi(d)\)
  3. \(\sum_{d|n}^n\varphi(d)=n\)
  4. \(i^k·(\frac{n}{i})^k=n^k\)

例子:


\(S(n)=\sum_{i=1}^n\mu(i)\)。

令 \(g(n)=1\),也即常函数。

则 \(\sum_{i=1}^n(g\times \mu)(i)=[n\ge 1]\)

\[S(n)=[n\ge 1]-\sum_{i=2}^nS(\lfloor\frac{n}{i}\rfloor) \]


\(S(n)=\sum_{i=1}^n\varphi(i)\)

令 \(g(n)=1\)

则 \(\sum_{i=1}^n(g\times \varphi)(i)=\frac{n(n+1)}{2}\)。

\[S(n)=\frac{n(n+1)}{2}-\sum_{i=2}^nS(\lfloor\frac{n}{i}\rfloor) \]


实操

计算 \(\sum_{i=1}^n\sum_{j=1}^nij\gcd(i,j)\)

先化简:

\[\begin{aligned} \sum_{i=1}^n\sum_{j=1}^nij\gcd(i,j)&=\sum_{d=1}^n\sum_{i=1}^n\sum_{j=1}^n[\gcd(i,j)=d]ijd\\ &=\sum_{d=1}^n\sum_{i=1}^{id\le n}\sum_{j=1}^{jd\le n}[\gcd(i,j)=1]ijd^3\\ &=\sum_{d=1}^nd^3\sum_{i=1}^{id\le n}\sum_{j=1}^{jd\le n}\sum_{t|i,t|j}\mu(t)ij\\ &=\sum_{x=1}^n\sum_{t=1}^{xt\le n}x^3\mu(t)\sum_{i=1}^{i\le \lfloor\frac{n}{xt}\rfloor}\sum_{j=1}^{j\le \lfloor\frac{n}{xt}\rfloor}ijt^2\\ &=\sum_{x=1}^n\sum_{t=1}^{xt\le n}x^3\mu(t)t^2\left(\frac{\lfloor\frac{n}{xt}\rfloor(\lfloor\frac{n}{xt}\rfloor+1)}{2}\right)^2\\ &=\sum_{T=1}^nT^2\sum_{d|T}\mu(d)\frac{T}{d}\left(\frac{\lfloor\frac{n}{T}\rfloor(\lfloor\frac{n}{T}\rfloor+1)}{2}\right)^2\\ &=\sum_{T=1}^nT^2\varphi(T)\left(\frac{\lfloor\frac{n}{T}\rfloor(\lfloor\frac{n}{T}\rfloor+1)}{2}\right)^2\\ \end{aligned} \]

令 \(h(n)=\frac{n^2(n+1)^2}{4}\),\(f(n)=n^2\varphi(n)\)。

对于上式,后者可以数论分块,问题化为求解 \(f\) 的前缀和。

令 \(g(n)=n^2\)

则 \(\sum_{i=1}^n(f\times g)(i=\sum_{i=1}^n\sum_{d|i}d^2\varphi(d)\times \frac{i^2}{d^2}=\sum_{i=1}^ni^3=\frac{n^2(n+1)^2}{4}\)

则 \(g(1)=1\)

则 \(g(i)\) 可以快速计算。

所以 \(S_f(n)=\frac{n^2(n+1)^2}{4}-\sum_{i=2}^ni^2S_f(\lfloor\frac{n}{i}\rfloor)\)

数论分块即可。

模版代码一份。

#include<bits/stdc++.h>
using namespace std;
#define N 1050500
#define int long long 
const int it=1e6+7;
int v[N],pri[N],tot,p,phi[N],n,m,s[N],inv2,inv6,inv4;
int power(int a,int b){
    int ans=1;
    while(b){
        if(b&1)ans=ans*a%p;
        a=a*a%p;b>>=1;
    }
    return ans;
}
unordered_map<int,int>sit;
void init(){
    phi[1]=1;
    for(int i=2;i<it;i++){
        if(!v[i]){
            pri[++tot]=i;phi[i]=i-1;
        }
        for(int j=1;j<=tot&&i*pri[j]<it;++j){
            v[pri[j]*i]=1;
            if(i%pri[j]==0){
                phi[pri[j]*i]=pri[j]*phi[i];break;
            }
            phi[pri[j]*i]=phi[pri[j]]*phi[i];
        }
    }
    for(int i=1;i<it;++i)s[i]=(s[i-1]+i*i%p*phi[i]%p)%p;
}
int h(int n){
    n%=p;
    return n*n%p*(n+1)%p*(n+1)%p*inv4%p;
}
int pfs(int n){
    n%=p;
    return n*(n+1)%p*(n+n+1)%p*inv6%p;    
}
int calc(int n){
    if(n<it)return s[n];
    if(sit[n]!=0)return sit[n];
    int res=h(n);int lst=1,cur=0;
    for(int l=2,r;l<=n;l=r+1){
        r=min(n,n/(n/l));cur=pfs(r);
        res=(res+p-(cur-lst)%p*calc(n/l)%p)%p;lst=cur;
    }res=(res%p+p)%p;
    return sit[n]=res;
}
signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>p;cin>>n;inv2=power(2,p-2);inv4=power(4,p-2);inv6=power(6,p-2);
    init();
    int ans=0,lst=0;
    for(int l=1,r;l<=n;l=r+1){
        r=min(n,n/(n/l));int cur=calc(r);
        ans+=(cur-lst)*h(n/l)%p;ans%=p;lst=cur;
    }
    ans=(ans%p+p)%p;
    cout<<ans<<"\n";
}

标签:lfloor,le,frac,入门,int,sum,rfloor,杜教
From: https://www.cnblogs.com/spdarkle/p/18309279

相关文章

  • ctfshow web入门 xss web327--web333 存储型和七七八八的
    存储型漏洞web327这道题貌似和反射型的xss差不多,直接打就行web328body和svg的好像不行<script>window.open('http://ceye地址/'+document.cookie)</script><script>window.open('http://hrcgnc.ceye.io/'+document.cookie)</script>先注册,密码多于6位很明显在这......
  • Linux入门---(二)shell命令
    1.1man获得帮助信息help只能查询内嵌命令,外部命令查询格式:命令--help1.2快捷键ctrl+u,清空当前已输入,但未执行的命令1.3文件目录类从根目录/开始的就是绝对路径,从当前文件夹开始的就是相对路径pwd显示当前工作目录的绝对路径ls列出目录的内容(ls-a列出全部文件)cd切......
  • 华为MindSpore入门
    总体介绍MindSpore是华为开发的全场景AI计算框架,旨在提供高效、灵活、安全的深度学习平台,适用于端、边、云等多种场景。作为一个开源项目,MindSpore支持多种硬件平台,提供简洁易用的API,使开发者能够快速构建、训练和部署深度学习模型。主要特点:全场景支持:适用于端、边、......
  • 深度学习框架入门
    #一句话说明白深度学习框架有什么用:利用编程语言来实现复杂的网络架构。不同的开发框架类似不同的语言。常见主流框架介绍 TensorFlow主要用于构建和训练深度学习模型。其强大的可视化工具(如TensorBoard)和对多种硬件的支持,使其在企业级和研究级应用中广泛使用。然而,Ten......
  • njs最详细的入门手册:Nginx JavaScript Engine
    原文链接:https://hi.imzlh.top/2024/07/08.cgi关于njs首先,njs似乎在国内外都不受关注,资料什么的只有官网参考手册,出了个问题只能看到GithubIssue所以,这篇文章将我的探索过程展示给大家,njs对于可用存储空间较小的设备真的很友好,相比较于NodeJS、Deno这种80M起步的运行环境真的......
  • 数据科学入门之关于jupyter notebook的基本使用及numpy数据库的基本调用(内含一些报错
    前言介绍一下数据科学  在IBM(国际商用机器公司)官网上对数据科学的解释是数据科学将数学和统计学、专业编程、高级分析,人工智能和机器学习与特定主题专业知识相结合,获取隐藏在组织数据中的切实可行的洞察。这些洞察可用于指导决策和战略规划。  关于数据科学,我十分喜......
  • Python包管理入门
    包管理器,是现代项目管理的重要组成部分,许多现代编程语言也会推出统一的包管理器以提升开发者体验,如rust的cargo,nodejs的npm,arkts的ohpm等等。Python作为一门很“新”的语言,自然也提供包管理功能。Python包管理的前世今生如果要提到Python的包管理,那么必定绕不开PYPI(Pytho......
  • Python入门基础 2--变量与基本数据类型
    1、程序员必备修养---注释注释=说明文档,说明代码的作用,让别人或者自己看代码的时候可以更好理解相关含义因为注释是给开发人员看的,不会参与程序运行python有两种注释方式:   1.单行注释-->用#符号表示,在#后面的内容都是注释print('第二篇文章')#这是输出语句 ......
  • C#基础入门
    C#作为一门高级编程语言,其实他和Java非常类似,如果有学习过Java语言的小伙伴,应该会对C#特别熟悉。如果你对C#语言不熟悉也没有关系,本文将会从头开始带你熟悉C#的知识点。在学习之前,我们要明白:每天学习做好笔记,思维导图。不是为了以后更好复习,而是为了能够更好的梳......
  • 分块入门
    基本思想把一个需要操作的序列分成若干块,分别处理,从而优化时间复杂度。容易证明块长为\(\sqrtn\)时复杂度最优。分块常规单次操作复杂度为\(\mathcal{O}(\sqrtn)\),一般可以当做\(\mathcal{O}(\log^2n)\)来计算复杂度。接下来给几道例题。T1给出一个长为\(n\)的数列......