洛谷题面传送门

一道其实算得上常规的题,写这篇题解是为了总结一些数论中轻微(?)优化复杂度的技巧。

首先感性理解可以发现该问题强于区间数颜色问题,无法用常用的 log 数据结构维护,因此考虑分块/莫队。显然这题莫队比较好些对吧?显然我们要对每个质因子计算一遍它在 \([l,r]\) 中的出现次数对吧?涉及质因子就要分解质因数对吧?莫队时候新添一个元素很明显就要枚举它的每个质因子,然后计算新添的贡献对吧?线性预处理乘法逆元以后,复杂度就变成了 \(n\sqrt{a_i}+(n+q)\sqrt{n}\omega(a_i)\),其中左边的分解质因数的复杂度,右边是莫队的复杂度,对吧?恭喜你,你完美地获得了 TLE 的好成绩。

考虑优化。加号左右两部分显然都不可行,都要进行优化。左边一部分相对比较容易:考虑预处理出 \([1,\sqrt{a_i}]\) 中所有质因子,这样每次分解不必 \([1,\sqrt{a_i}]\) 跑一遍,只用跑其中 \(\mathcal O(\dfrac{\sqrt{a_i}}{\ln\sqrt{a_i}})\) 个质因子即可,这样左边的复杂度就变成了 \(\dfrac{\sqrt{a_i}}{\ln\sqrt{a_i}}·n\)。再考虑右边,注意到在每个数所有不同质因子中,大部分都比较小,因此考虑用类似于根号分治的方法,我们预处理 \([1,\sqrt[3]{a_i}]\) 中所有质因子,对于 \([1,\sqrt[3]{a_i}]\) 中质因子的贡献,我们直接前缀和扫一遍即可计算,复杂度 \((n+q)\pi(\sqrt[3]{a_i})\),对于 \(>\sqrt[3]{a_i}\) 的质因子的贡献就按照上面的方法进行莫队。注意到一个数最多有 \(2\) 个 \(>\sqrt[3]{a_i}\) 的因子,因此莫队的 \(\omega\) 就变成了常数,总复杂度也进而变为 \(\dfrac{\sqrt{a_i}}{\ln\sqrt{a_i}}·n+(n+q)\pi(\sqrt[3]{a_i})+(n+q)\sqrt{n}\)。

const int MAXN=1e5;
const int MAXV=31630;
const int LIM=1000;
const int PI_LIM=220;
const int MAXX=1e6;
const int BLK=316;
int n,qu,a[MAXN+5];
int pr[MAXV/6+5],prcnt=0,vis[MAXV+5];
void sieve(int n){
for(int i=2;i<=n;i++){
if(!vis[i]) pr[++prcnt]=i;
for(int j=1;j<=prcnt&&pr[j]*i<=n;j++){
vis[pr[j]*i]=1;if(i%pr[j]==0) break;
}
}
}
int c[MAXN+5][3],cc[MAXN+5];
int sum[MAXN+5][PI_LIM+5],inv[MAXX+5];
int res[MAXN+5],bel[MAXN+5],L[BLK+5],R[BLK+5],blk_sz,blk_cnt;
int key[MAXN*2+5],uni[MAXN*2+5],ccnt=0,num=0;
struct qry{
int l,r,id;
bool operator <(const qry &rhs){
if(bel[l]^bel[rhs.l]) return bel[l]<bel[rhs.l];
else if(bel[l]&1) return r<rhs.r;
else return r>rhs.r;
}
} q[MAXN+5];
int cnt[MAXN*2+5],mul=1;
void ins(int x){
for(int i=1;i<=cc[x];i++){
mul=1ll*mul*inv[cnt[c[x][i]]+1]%MOD;
cnt[c[x][i]]++;
mul=1ll*mul*(cnt[c[x][i]]+1)%MOD;
}
}
void del(int x){
for(int i=1;i<=cc[x];i++){
mul=1ll*mul*inv[cnt[c[x][i]]+1]%MOD;
cnt[c[x][i]]--;
mul=1ll*mul*(cnt[c[x][i]]+1)%MOD;
}
}
int main(){
scanf("%d%d",&n,&qu);sieve(MAXV);
blk_sz=(int)sqrt(n);blk_cnt=(n-1)/blk_sz+1;
for(int i=1;i<=blk_cnt;i++){
L[i]=(i-1)*blk_sz+1;R[i]=min(i*blk_sz,n);
for(int j=L[i];j<=R[i];j++) bel[j]=i;
}
for(int i=(inv[0]=inv[1]=1)+1;i<=MAXX;i++) inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
int tmp=a[i];
for(int j=1;j<=prcnt;j++) if(tmp%pr[j]==0){
int cnt=0;
while(tmp%pr[j]==0) tmp/=pr[j],cnt++;
if(pr[j]<=LIM) sum[i][j]=cnt;
else{
c[i][++cc[i]]=pr[j];
if(cnt==2) c[i][++cc[i]]=pr[j];
}
} if(tmp>1) c[i][++cc[i]]=tmp;
for(int j=1;j<=cc[i];j++) key[++ccnt]=c[i][j];
} sort(key+1,key+ccnt+1);
for(int i=1;i<=n;i++) for(int j=1;j<=prcnt;j++){
if(pr[j]>LIM) break;sum[i][j]+=sum[i-1][j];
}
for(int i=1;i<=ccnt;i++) if(key[i]^key[i-1]) uni[++num]=key[i];
for(int i=1;i<=n;i++) for(int j=1;j<=cc[i];j++)
c[i][j]=lower_bound(uni+1,uni+num+1,c[i][j])-uni;
for(int i=1;i<=qu;i++){
scanf("%d%d",&q[i].l,&q[i].r);q[i].id=i;res[i]=1;
for(int j=1;j<=prcnt;j++){
if(pr[j]>LIM) break;
res[i]=1ll*res[i]*(sum[q[i].r][j]-sum[q[i].l-1][j]+1)%MOD;
}
} sort(q+1,q+qu+1);int cl=1,cr=0;
for(int i=1;i<=qu;i++){
while(cr<q[i].r) ins(++cr);
while(cl>q[i].l) ins(--cl);
while(cl<q[i].l) del(cl++);
while(cr>q[i].r) del(cr--);
res[q[i].id]=1ll*res[q[i].id]*mul%MOD;
}
for(int i=1;i<=qu;i++) printf("%d\n",res[i]);
return 0;
}

洛谷 P5071 - [Ynoi2015] 此时此刻的光辉(莫队)的更多相关文章

  1. Bzoj2120/洛谷P1903 数颜色(莫队)

    题面 Bzoj 洛谷 题解 考虑对操作离线后分块处理询问操作(莫队算法),将询问操作按照编号分块后左端点第一关键字,右端点第二关键字排序(分块大小为\(n^{\frac 23}\)),对于每一个询问操 ...

  2. 【题解】Luogu P5071 [Ynoi2015]此时此刻的光辉

    众所周知lxl是个毒瘤,Ynoi道道都是神仙题,题面好评 原题传送门 一看这题没有修改操作就知道这是莫队题(我也只会莫队) 我博客里对莫队的简单介绍 一个数N可以分解成\(p_1^{c_1}p_2^{ ...

  3. 洛谷P3901 数列找不同 [莫队]

    题目传送门 题目描述 现有数列 A_1,A_2,\cdots,A_NA1​,A2​,⋯,AN​ ,Q 个询问 (L_i,R_i)(Li​,Ri​) , A_{Li} ,A_{Li+1},\cdots, ...

  4. 洛谷P3245 [HNOI2016]大数 【莫队】

    题目 题解 除了\(5\)和\(2\) 后缀数字对\(P\)取模意义下,两个位置相减如果为\(0\),那么对应子串即为\(P\)的倍数 只用对区间种相同数个数\(x\)贡献\({x \choose 2 ...

  5. P5071 [Ynoi2015]此时此刻的光辉

    传送门 lxl大毒瘤 首先一个数的因子个数就是这个数的每个质因子的次数+1的积,然后考虑把每个数分解质因子,用莫队维护,然后我交上去就0分了 如果是上面那样的话,我们每一次移动指针的时间复杂度是O(这 ...

  6. 洛谷 P4887 -【模板】莫队二次离线(第十四分块(前体))(莫队二次离线)

    题面传送门 莫队二次离线 mol ban tea,大概是这道题让我第一次听说有这东西? 首先看到这类数数对的问题可以考虑莫队,记 \(S\) 为二进制下有 \(k\) 个 \(1\) 的数集,我们实时 ...

  7. 洛谷P3901 数列找不同(莫队水题)

    重温下手感,判断区间是否全是不同的数字有两种做法,一个长度为len的区间不同的数字,参见HH的项链,一种是区间众数,参见蒲公英,是水题没错了.明天搞数据库,然后继续自己的gre和训练计划 #inclu ...

  8. [Ynoi2015]此时此刻的光辉(莫队)

    一道神题...自己写出来以后被卡常了...荣获洛谷最差解... 思路还是比较好想,对于每个数 \(\sqrt{n}\) 分块,对于 \(\sqrt{n}\) 以内的数,我们可以直接求出来.对于 \(\ ...

  9. Luogu5071 [Ynoi2015]此时此刻的光辉 【莫队】

    题目链接:洛谷 这个跟上上个Ynoi题目是一样的套路,首先我们知道\(n=\prod p_i^{\alpha_i}\)时\(d(n)=\prod (\alpha_i+1)\). 首先对所有数分解质因数 ...

随机推荐

  1. 2021.10.26考试总结[冲刺NOIP模拟16]

    T1 树上的数 \(DFS\)一遍.结构体存边好像更快? \(code:\) T1 #include<bits/stdc++.h> using namespace std; namespa ...

  2. 用Python画如此漂亮的专业插图 ?简直So easy!

    本文整理自知乎问答,仅用于学术分享,著作权归作者所有.如有侵权,请联系我删文处理.多多转发,多多学习! 方法一 强烈推荐 Python 的绘图模块 matplotlib: python plottin ...

  3. 使用spire.doc导出支持编辑Latex公式的标准格式word

    背景 之前有的教辅标注需求,在导出题库的时候希望顺便导出可以查看word,方便线下预览成品效果,因为只是用来预览并且为了沿用前端的样式,当时方案就是直接生成html,写个word的文件头,这样就可以用 ...

  4. cf13B Letter A(分类+简单计算几何,,)

    题意: 给三个线段(每个线段的两个端点的坐标),问这三个线段能否组成字母A. 组成字母A的条件: 1.两个线段有公共端点. 2.这两个线段夹角小于等于90度. 3.第三个线段的两个端点分别在这两个线段 ...

  5. poj 2311 Cutting Game (SG)

    题意: 有一张W*H的纸片. 每人每次可以横着撕或者竖着撕,先撕出1*1那一方胜. 数据范围: W and H (2 <= W, H <= 200) 思路: 很好抽象出游戏图的模型,用SG ...

  6. 第01课 OpenGL窗口(4)

    下面的代码处理所有的窗口消息.当我们注册好窗口类之后,程序跳转到这部分代码处理窗口消息. LRESULT CALLBACK WndProc( HWND hWnd, // 窗口的句柄 UINT uMsg ...

  7. vue中element-ui table列名lable换行问题 ---亲测

    1.lable操作 :label = "'xxxxx \n xxxxx'" // 注意 lable 的: 注:双引号内有单引号,这样才可以解析文本.需要换行的文本处添加 \n 2. ...

  8. Mysql—— 内连接、左连接、右连接以及全连接查询

    CREATE TABLE `a_table` ( `a_id` int(11) DEFAULT NULL, `a_name` varchar(10) DEFAULT NULL, `a_part` va ...

  9. LeetCode刷题 二分专题

    二分专题 二分的题目类型 对于满足二段性的题目的两套模板 模板一 模板如下 模板二 模板如下 解决二分题目的一般流程 LeeCode实战 LC69.x的平方根 解法思路 LC35.搜索插入位置 解法思 ...

  10. wm_concat结果长度限制的有关问题 ORA-06502: PL/SQL: 数字或值错误

    该函数作用是把列值合并(用英文逗号分割),但是数量有限制,返回的字符数上线是4000(oracle11g),超过会报错,听说oracle版本到 11.2.0.2.0 或以上返回的是clob类型,长度就 ...