0%

思路讲解

AC代码

https://codeforces.com/contest/2133/submission/335376194

心路历程(WA,TLE,MLE……)

思路讲解

简单来说,就是对

gcd递推方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
FOR(i,0,blocksz){
FOR(j,0,blocksz){
if(i==0 || j==0){
GCD[i][j]=i+j;
continue;
}
if(i>j){
GCD[i][j]=GCD[i-j][j];
}else{
GCD[i][j]=GCD[i][j-i];
}
}
}

这个块长也比较玄学,siz=NMsiz=\frac{N}{\sqrt M})是过不了的,siz=N2Msiz=\frac{N}{2\sqrt M} 就可以过了,siz=N4Msiz=\frac{N}{4\sqrt M} 更快?其实我感觉要正确生成块长,主要还是要根据这个真正需要这个块长的东西决定的。

在这一堆操作中,真正需要用到块长会增加复杂度的操作,比用块长可以减少复杂度的多,因此,取较小的块长可以加快速度。

可以看到,负担操作执行的更多,因此可以减少块长。

image

这个也是一个小技巧。

1
2
3
// 比如说d=2,其实我们就是想知道k有几个可以除以2的因数
// 求这个O(1)比较难,但可以求k先除以2,即k/2有几个因数
ismul[d]+=SZ(divv[k/d])*x;

AC代码

https://vjudge.net/solution/63198297

心路历程(WA,TLE,MLE……)

思路讲解

呃,没什么好说的,主要就是一些细节问题

pushdown顺序放在这里了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void pushdown(int o){
int l=o<<1,r=l|1; // 左儿子,右儿子
if(tag2[o]!=initv){
settag2(l, tag2[o]);
settag2(r, tag2[o]);
tag2[o]=initv;
}
if(tag3[o]!=1){
settag3(l, tag3[o]);
settag3(r, tag3[o]);
tag3[o]=1;
}
if(tag[o]!=0){
settag(l, tag[o]);
settag(r, tag[o]);
tag[o]=0;
}
}

AC代码

https://vjudge.net/solution/63174043

心路历程(WA,TLE,MLE……)

思路讲解

就是简单的东西。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
FOR(_,1,M){
ll l,r;
cin>>l>>r;
ll ret=tr.query(l, r);
tr.modify(l, r, 0);
ll res=ret*binpow(r-l+1, mod-2)%mod;
tr.add(l, r, res);
}
FOR(i,1,tr.sz-1){
tr.pushdown(i);
}
FOR(i,1,N){
ll res=tr.tr[i+tr.sz];
if(res<0) res+=mod;
cout<<res<<" ";
}

AC代码

心路历程(WA,TLE,MLE……)