题目大意:

给定一个序列,每次询问一段区间的数的乘积的约数个数。

解题思路:

在太阳西斜的这个世界里,置身天上之森。等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去、逐渐消逝的未来。我回来了,纵使日薄西山,即便看不到未来,此时此刻的光辉,盼君勿忘。————世界上最幸福的女孩

我永远喜欢珂朵莉。

---

\(10^9\)以内的数最多有10个不同的质因子。

考虑对其质因数分解。

由于值域范围过大,考虑使用Pollard-Rho算法。

这里普通的Pollard-Rho算法可能会TLE。如果你的代码能通过模板题,那基本上没问题(窝反正直接把以前写的板子拉过来然后调了调参)。

之后,你就会得到最多\(10n\)个不同的质因数。对其进行离散化,开桶记录。

然后上莫队,对于每次指针的偏移,把它所有的质因数加到桶里,同时维护约数个数即可。

这部分时间复杂度\(O(10n\sqrt n)\),加上上面的质因数分解的玄学期望复杂度,只能获得82分的好成绩。

---

我们考虑把每个数\(1000\)以内的质因子先取出来(\(1000\)以内共168个质数),然后,对其做前缀和,记录前缀的出现次数。

然后,由于\(1001^3>10^9\),所以每个数剩下最多不超过2个质因子。这部分用Pollard_Rho找即可。

然后莫队的时候,对于前面168个质数就可以不用维护,直接用前缀和。

而对于后面的大质因子,再离散化处理即可。由于每个数最多两个质因子,所以常数就小了很多。

而由于筛掉了很多小的质因子,Pollard_Rho的速度也会变快。然后就足以通过此题。

C++ Code:

#include<cctype>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cstring>
#define ctz __builtin_ctz
using namespace std;
#ifdef ONLINE_JUDGE
struct istream{
char buf[23333333],*s;
inline istream(){
buf[fread(s=buf,1,23333330,stdin)]='\n';
fclose(stdin);
}
inline istream&operator>>(int&d){
d=0;
for(;!isdigit(*s);++s);
while(isdigit(*s))
d=(d<<3)+(d<<1)+(*s++^'0');
return*this;
}
}cin;
struct ostream{
char buf[8000005],*s;
inline ostream(){s=buf;}
inline ostream&operator<<(int d){
if(!d){
*s++='0';
}else{
static int w;
for(w=1;w<=d;w*=10);
for(;w/=10;d%=w)*s++=d/w^'0';
}
return*this;
}
inline ostream&operator<<(const char&c){*s++=c;return*this;}
inline void flush(){
fwrite(buf,1,s-buf,stdout);
s=buf;
}
inline~ostream(){flush();}
}cout;
#else
#include<iostream>
#endif
int pri[170],cct=0,sum[100005][169],num[1005];
void sieve(){
for(int i=2;i<=1000;++i)num[i]=1;
for(int i=2;i<=1000;++i)
if(num[i]){
pri[num[i]=++cct]=i;
for(int j=i<<1;j<=1000;j+=i)num[j]=0;
}
}
using LoveLive=long long;
vector<int>tj;
const int pr[]={2,3,5,24251,61,19260817};
int gcd(int a,int b){
if(!a||!b)return a|b;
int t=ctz(a|b);
a>>=ctz(a);
do{
b>>=ctz(b);
if(a>b)swap(a,b);
b-=a;
}while(b);
return a<<t;
}
inline int power(int a,int b,const int&md){
int ans=1;
for(;b;b>>=1){
if(b&1)ans=(LoveLive)ans*a%md;
a=(LoveLive)a*a%md;
}
return ans;
}
int miller_rabin(int p){
if(p==2)return 1;
int b=p-1;
int t=0;
while(!(b&1))b>>=1,++t;
for(int i:pr){
int r=power(i%(p-2)+2,b,p);
if(r==1||r==p-1)continue;
int ok=1;
for(int j=1;j<=t&&ok;++j){
r=(LoveLive)r*r%p;
if(r==p-1)ok=0;
}
if(ok)return 0;
}
return 1;
}
void pollard_rho(int&n,int c){
int k=2,x=rand()%(n-1)+1,y=x,q=1,t=1;
for(;;k<<=1,y=x,q=1){
for(int i=1;i<=k;++i){
x=((LoveLive)x*x%n+c)%n;
q=(LoveLive)q*abs(x-y)%n;
if(!(i&63)){
t=gcd(q,n);
if(t>1)break;
}
}
if(t>1||(t=gcd(q,n))>1)break;
}
n=t;
}
void find(int n,int c){
if(n==1)return;
if(miller_rabin(n)){tj.push_back(n);return;}
int p=n;
while(p>=n)pollard_rho(p,c--);
n/=p;
tj.push_back(n),tj.push_back(p);
}
#define N 100005
const int md=19260817;
int n,m,a[N],inv[N],cnt[N],tot[N*2],now=1,ans[N];
int p[N][3];
vector<int>lr;
struct que{
static const int siz=317;
int l,r,id;
inline bool operator<(const que&rhs)const{
return((l/siz!=rhs.l/siz)?(l<rhs.l):r<rhs.r);
}
}q[N];
inline void add(int id){
for(register int i=1;i<=cnt[id];++i)
now=(LoveLive)now*inv[tot[p[id][i]]]%md*(tot[p[id][i]]+1)%md,++tot[p[id][i]];
}
inline void del(int id){
for(register int i=1;i<=cnt[id];++i)
now=(LoveLive)now*inv[tot[p[id][i]]]%md*(tot[p[id][i]]-1)%md,--tot[p[id][i]];
}
int main(){
srand(19260817);
sieve();
cin>>n>>m;
inv[1]=1;
for(int i=2;i<=n;++i)inv[i]=(md-md/i)*1LL*inv[md%i]%md;
for(int i=1;i<=n;++i){
cin>>a[i];
memcpy(sum[i],sum[i-1],sizeof*sum);
for(int j=1;j<=cct&&pri[j]*pri[j]<=a[i];++j)
while(!(a[i]%pri[j])){
++sum[i][j];
a[i]/=pri[j];
}
if(a[i]>1){
if(a[i]<=pri[cct]){
++sum[i][num[a[i]]];
continue;
}
tj.clear();
find(a[i],23333);
for(int it:tj)
p[i][++cnt[i]]=it,lr.push_back(it);
}
}
sort(lr.begin(),lr.end());
lr.erase(unique(lr.begin(),lr.end()),lr.end());
for(int i=1;i<=n;++i)
for(int j=1;j<=cnt[i];++j)p[i][j]=lower_bound(lr.begin(),lr.end(),p[i][j])-lr.begin();
for(int i=1;i<=m;++i)cin>>q[q[i].id=i].l>>q[i].r;
sort(q+1,q+m+1);
for(int i=0;i<n<<1;++i)tot[i]=1;
for(int i=1,l=1,r=0;i<=m;++i){
while(r<q[i].r)add(++r);
while(l>q[i].l)add(--l);
while(r>q[i].r)del(r--);
while(l<q[i].l)del(l++);
int&out=ans[q[i].id];out=now;
for(int j=1;j<=cct;++j)
out=(LoveLive)out*(sum[r][j]-sum[l-1][j]+1)%md;
}
for(int i=1;i<=m;++i)
cout<<ans[i]<<'\n';
return 0;
}

  

[Ynoi2015]此时此刻的光辉的更多相关文章

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

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

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

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

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

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

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

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

  5. 洛谷 P5071 - [Ynoi2015] 此时此刻的光辉(莫队)

    洛谷题面传送门 一道其实算得上常规的题,写这篇题解是为了总结一些数论中轻微(?)优化复杂度的技巧. 首先感性理解可以发现该问题强于区间数颜色问题,无法用常用的 log 数据结构维护,因此考虑分块/莫队 ...

  6. 洛谷P5071 此时此刻的光辉

    2s512M. 解:先分解质因数.考虑按照质因数大小是否大于√分类. 大于的就是一个数颜色个数,莫队即可n√m. 小于的直接枚举质因数做前缀和然后O(1)查询.总时间复杂度n(√m + σ(√V)). ...

  7. 【题解】Luogu P5313 僕たちはひとつの光([Ynoi2012]D2T2)

    原题传送门 lovelive好评 比赛时只拿到了60pts,还是自己太菜了 这题的思想实际有点像Luogu P3674 小清新人渣的本愿与Luogu P5071 [Ynoi2015]此时此刻的光辉 这 ...

  8. [Ynoi2015]即便看不到未来

    题目大意: 给定一个序列,每次询问,给出一个区间$[l,r]$. 设将区间内的元素去重后重排的数组为$p$,求$p$中长度为$1\sim 10$的极长值域连续段个数. 长度为$L$的极长值域连续段的定 ...

  9. [Ynoi2015]纵使日薄西山

    题目大意: 给定一个序列,每次单点修改,然后进行询问. 定义一次操作为,选择一个位置$x$,将这个位置的数和左边.右边两个位置的数(不存在则忽略)各减去1,然后和0取max. 对序列中最大的位置进行一 ...

随机推荐

  1. nyoj891(区间上的贪心)

    题目意思: 给一些闭区间,求最少须要多少点,使得每一个区间至少一个点. http://acm.nyist.net/JudgeOnline/problem.php?pid=891 例子输入 4 1 5 ...

  2. android graphic(15)—fence

    为何须要fence fence怎样使用 软件实现的opengl 硬件实现的opengl 上层使用canvas画图 上层使用opengl画图 下层合成 updateTexImage doComposeS ...

  3. 利用安卓手机搭建WEB服务器

    背景介绍 Android是一种基于Linux的自由及开放源代码的操作系统 所以是用安卓来搭建服务器是完全可行的.接下来将教大家如何利用AndroPHP和Feel FTP(或者其他FTP管理器)来在安卓 ...

  4. PCB Genesis加二维码 实现方式

    使用incam可以很轻松的增加2维码,这里通过另外一种方式玩转二维码的加法, 使用谷歌zxing.dll类库实现,将文字信息转为bitmap点阵后,在Genesis绘制点即可. 一.incam增加二维 ...

  5. PCB 生产周期计算逻辑与代码实现

    PCB生产周期计算逻辑: 代码实现: 调用代码: getWeek(DateTime.Now.Date, ); 周期计算逻辑: /// <summary> /// 获取周期 /// < ...

  6. Gym - 101981J The 2018 ICPC Asia Nanjing Regional Contest J.Prime Game 计数

    题面 题意:1e6的数组(1<a[i]<1e6),     mul (l,r) =l × (l+1) ×...× r,  fac(l,r) 代表 mul(l,r) 中不同素因子的个数,求s ...

  7. [JZOJ3809]设备塔

    其实我并没有JZOJ的号...但既然dalao说了是JZOJ上的题,那就是了吧...... 为了封印辉之环,古代塞姆利亚大陆的人民在异空间中建造了一座设备塔. 简单的说,这座设备塔是一个漂浮在异空间中 ...

  8. Ubuntu下搭建repo服务器(一): 配置gitosis

    1. 说明 服务器端IP: 192.168.1.126,下文简称:A端: 客户端IP: 192.168.130.19,下文简称:B端: Android工程代号:17435. 2. 安装必要软件(A端) ...

  9. doctype声明 过渡transitional 严格strict 框架frameset

    DOCTYPE是document type(文档类型)的简写,用来说明你用的XHTML或者HTML是什么版本. 其中的DTD(例如上例中的xhtml1-transitional.dtd)叫文档类型定义 ...

  10. Beta冲刺-星期四

    这个作业属于哪个课程  <课程的链接>            这个作业要求在哪里 <作业要求的链接> 团队名称 Three cobblers 这个作业的目标 完成今天的冲刺 一 ...