【BZOJ3529】[SDOI2014] 数表(莫比乌斯反演)

本文详细解析了BZOJ3529数表问题,通过数学推导和算法优化,提出了有效的解决方案。利用线性筛求解σ函数,结合树状数组维护限制条件,实现了高效计算。

点此看题面

大致题意: 规定一个\(n*m\)数表中每个数为\(\sum_{d|i,d|j}d\),求数表中不大于\(a\)的数之和。

不考虑限制

我们先不考虑限制,来推一波式子。

首先,易知数表中第\(i\)行第\(j\)列的数应该是\(\sigma(gcd(i,j))\)

则和就为:

\[\sum_{d=1}^{min(n,m)}\sigma(d)\sum_{i=1}^{\lfloor\frac nd\rfloor}\sum_{j=1}^{\lfloor\frac md\rfloor}[gcd(i,j)=1]\]

\([gcd(i,j)=1]\)可以化成\(\sum_{p|gcd(i,j)}\mu(p)\),若枚举\(p\),就得到:

\[\sum_{d=1}^{min(n,m)}\sigma(d)\sum_{p=1}^{\lfloor\frac{min(n,m)}d\rfloor}\mu(p)\lfloor\frac n{dp}\rfloor\lfloor\frac m{dp}\rfloor\]

\(g=dp\),调整枚举顺序得到:

\[\sum_{g=1}^{min(n,m)}\lfloor\frac n{dp}\rfloor\lfloor\frac m{dp}\rfloor\sum_{d|g}\sigma(d)\mu(\frac gd)\]

离线处理限制

考虑上面的式子只有当\(\sigma(d)\le a\)时才会被计算答案。

则我们考虑设\(T(g)=\sum_{d|g}\sigma(d)\mu(\frac gd)\),一开始全为\(0\)

然后我们按照\(a\)从小到大枚举询问,每次将\(\sigma(d)\le a\)\(d\)\(10^5\)范围内的倍数所对应的\(T(g)\)全都加上\(\sigma(d)\mu(\frac gd)\)

但注意到询问时使用除法分块需要求一段区间的\(T\)值和,则我们用树状数组维护就可以了。

关于取模的细节

注意,这里的取模是向\(2^{31}\)取模,则我们可以考虑先开\(unsigned\ int\)计算答案,最后再将其向\(2^{31}\)取模

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define Q 20000
#define MxS 500000
#define UI unsigned
#define RU Reg unsigned
#define CU Con unsigned&
#define LL long long
#define Gmax(x,y) (x<(y)&&(x=(y)))
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
#define pb push_back
#define IT vector<int>::iterator
using namespace std;
int Qt,Qans[Q+5];vector<int> s[MxS+5];
struct Query//询问
{
    int x,y,v,pos;I Query(CI a=0,CI b=0,CI z=0,CI p=0):x(a),y(b),v(z),pos(p){}
    I bool operator < (Con Query& o) Con {return v<o.v;}
}q[Q+5];
class FastIO
{
    private:
        #define FS 100000
        #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
        #define pc(c) (C==E&&(clear(),0),*C++=c)
        #define tn (x<<3)+(x<<1)
        #define D isdigit(c=tc())
        int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
    public:
        I FastIO() {A=B=FI,C=FO,E=FO+FS;}
        Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
        Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
        Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
        Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
        I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
class LinearSiever//线性筛
{
    private:
        int Pt,P[N+5],Mn[N+5];
        I LL Qpow(LL x,LL y) {LL t=1;W(y) y&1&&(t*=x),x*=x,y>>=1;return t;}//快速幂
    public:
        int MxSigma,sigma[N+5],mu[N+5];
        I void Sieve(CI S)
        {
            RI i,j,x,t;for(mu[1]=1,i=2;i<=S;++i)//筛mu,筛最小质因数用于求sigma
            {
                !Mn[i]&&(mu[P[++Pt]=i]=-1,Mn[i]=i);
                for(j=1;j<=Pt&&1LL*i*P[j]<=S;++j)
                    if(Mn[i*P[j]]=P[j],i%P[j]) mu[i*P[j]]=-mu[i];else break;
            }
            for(sigma[1]=1,i=2;i<=S;++i)//求sigma
            {
                x=i,t=0;W(!(x%Mn[i])) x/=Mn[i],++t;
                sigma[i]=sigma[x]*((Qpow(Mn[i],t+1)-1)/(Mn[i]-1)),Gmax(MxSigma,sigma[i]);
            }
        }
}L;
class TreeArray//树状数组
{
    private:
        #define lowbit(x) (x&-x)
        UI v[MxS+5];
        I UI QS(RI x) {RU t=0;W(x) t+=v[x],x-=lowbit(x);return t;}//询问前缀
    public:
        I void Add(RI x,CI y) {W(x<=L.MxSigma) v[x]+=y,x+=lowbit(x);}//单点修改
        I UI Qry(CI l,CI r) {return QS(r)-QS(l-1);}//区间查询
}T;
I void Upt(CI x,CI v) {for(RI i=1;1LL*x*i<=N;++i) T.Add(x*i,L.sigma[x]*L.mu[i]);}//更新一个数倍数的值
int main()
{
    RI i,p=1,t,x,y,v,l,r;UI ans;for(L.Sieve(N),i=1;i<=N;++i) s[L.sigma[i]].pb(i);//用桶对sigma值进行排序
    for(F.read(Qt),i=1;i<=Qt;++i) F.read(x,y,v),q[i]=Query(min(x,y),max(x,y),v,i);//读入询问
    for(sort(q+1,q+Qt+1),i=1;i<=Qt;++i)//对询问按a从小到大排序
    {
        W(p<=q[i].v) {for(IT it=s[p].begin();it!=s[p].end();++it) Upt(*it,p);++p;}//更新sigma(d)≤a的d的倍数的T值
        for(ans=0,t=min(q[i].x,q[i].y),l=1;l<=t;l=r+1)//除法分块
            r=min(q[i].x/(q[i].x/l),q[i].y/(q[i].y/l)),ans+=T.Qry(l,r)*(q[i].x/l)*(q[i].y/l);
        Qans[q[i].pos]=ans%(1LL<<31);//存储答案并取模
    }
    for(i=1;i<=Qt;++i) F.writeln(Qans[i]);return F.clear(),0;//输出答案
}

转载于:https://www.cnblogs.com/chenxiaoran666/p/BZOJ3529.html

标题基于Python的汽车之家网站舆情分析系统研究AI更换标题第1章引言阐述汽车之家网站舆情分析的研究背景、意义、国内外研究现状、论文方法及创新点。1.1研究背景与意义说明汽车之家网站舆情分析对汽车行业及消费者的重要性。1.2国内外研究现状概述国内外在汽车舆情分析领域的研究进展与成果。1.3论文方法及创新点介绍本文采用的研究方法及相较于前人的创新之处。第2章相关理论总结和评述舆情分析、Python编程及网络爬虫相关理论。2.1舆情分析理论阐述舆情分析的基本概念、流程及关键技术。2.2Python编程基础介绍Python语言特点及其在数据分析中的应用。2.3网络爬虫技术说明网络爬虫的原理及在舆情数据收集中的应用。第3章系统设计详细描述基于Python的汽车之家网站舆情分析系统的设计方案。3.1系统架构设计给出系统的整体架构,包括数据收集、处理、分析及展示模块。3.2数据收集模块设计介绍如何利用网络爬虫技术收集汽车之家网站的舆情数据。3.3数据处理与分析模块设计阐述数据处理流程及舆情分析算法的选择与实现。第4章系统实现与测试介绍系统的实现过程及测试方法,确保系统稳定可靠。4.1系统实现环境列出系统实现所需的软件、硬件环境及开发工具。4.2系统实现过程详细描述系统各模块的实现步骤及代码实现细节。4.3系统测试方法介绍系统测试的方法、测试用例及测试结果分析。第5章研究结果与分析呈现系统运行结果,分析舆情数据,提出见解。5.1舆情数据可视化展示通过图表等形式展示舆情数据的分布、趋势等特征。5.2舆情分析结果解读对舆情分析结果进行解读,提出对汽车行业的见解。5.3对比方法分析将本系统与其他舆情分析系统进行对比,分析优劣。第6章结论与展望总结研究成果,提出未来研究方向。6.1研究结论概括本文的主要研究成果及对汽车之家网站舆情分析的贡献。6.2展望指出系统存在的不足及未来改进方向,展望舆情
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值