洛谷题面传送门

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

首先感性理解可以发现该问题强于区间数颜色问题,无法用常用的 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. csp-j 复赛感想

    作者:博客园小蔡编程 这次是作者第一次参加csp-j的比赛 内心还是挺激动的 今天,作者就来和大家讨论一下这次csp-j的学习心得和感想 T1 分糖果 这题描述看似复杂 其实就是一道求最大取模的题 L ...

  2. 【UE4 C++】Print、Delay、ConsoleCommand

    基于UKismetSystemLibrary PrintString /** * Prints a string to the log, and optionally, to the screen * ...

  3. BPMN 學習實例

    什麼是業務流程圖? What is BPMN 業務流程建模符號(BPMN)是業務流程建模的一種方法.它基於統一建模語言(UML)中活動圖的概念,以圖形符號(業務流程圖)支持業務流程的規範.BPMN為企 ...

  4. Java:Iterator接口与fail-fast小记

    Java:Iterator接口与fail-fast小记 对 Java 中的 Iterator接口 和 fail-fast,做一个微不足道的小小小小记 Iterator Iterator接口 Itera ...

  5. Noip模拟67 2021.10.3

    还是困,不过已经可以用脑子思考问题了 T1 数据恢复 没啥明确的算法,可以说是贪心? 考虑部分分, 链的直接扫, 对于菊花的发现只要根节点在第一个,剩下的点位置不重要 那么按照$a/b$排序,扫一遍就 ...

  6. csp-s 2021

    T1 廊桥分配 当一架飞机抵达机场时,可以停靠在航站楼旁的廊桥,也可以停靠在位于机场边缘的远机位. 乘客一般更期待停靠在廊桥,因为这样省去了坐摆渡车前往航站楼的周折. 然而,因为廊桥的数量有限,所以这 ...

  7. STM32单片机的学习方法(方法大体适用所有开发版入门)

    1,一款实用的开发板. 这个是实验的基础,有时候软件仿真通过了,在板上并不一定能跑起来,而且有个开发板在手,什么东西都可以直观的看到,效果不是仿真能比的.但开发板不宜多,多了的话连自己都不知道该学哪个 ...

  8. max-points-on-a-line leetcode C++

    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...

  9. 更优于 Shellinabox 的 web shell 工具 -- ttyd

    ttyd 是一个运行在服务端,客户端通过web浏览器访问从而连接后台 tty (pts伪终端)接口的程序,把 shell 终端搬到 web 浏览器中. WebSocket WebSocket 是 HT ...

  10. SSH 提示密码过期,如何通过 ansible 批量更新线上服务器密码

    起因 线上环境是在内网,登陆线上环境需要使用 VPN + 堡垒机 登陆,但是我日常登陆线上环境都是 VPN + 堡垒机 + Socks5常驻代理,在shell端只需要保存会话,会话使用socks5代理 ...