====== Harbour.Space Scholarship Contest 2021-2022 (Div. 1 + Div. 2) ====== [[https://codeforces.com/contest/1553|比赛链接]] ===== F. Pairwise Modulo ===== ==== 题意 ==== 给定长度为 $n$ 且互不相同序列 $A$,对每个 $k=1\sim n$ 计算 $$ f(k)=\sum_{i=1}^k\sum_{j=1}^k a_i\bmod a_j $$ ==== 题解 ==== 不难发现 $$ f(k)=f(k-1)+\sum_{i=1}^k a_i\bmod a_k+\sum_{i=1}^k a_k\bmod a_i\\ \sum_{i=1}^k a_i\bmod a_k=\sum_{i=1}^{k-1}a_i-\sum_{i=1}^{k-1}\lfloor \frac {a_i}{a_k}\rfloor a_k\\ \sum_{i=1}^k a_k\bmod a_i=(k-1)a_k-\sum_{i=1}^{k-1}\lfloor \frac {a_k}{a_i}\rfloor a_i\\ $$ 对于 $\sum_{i=1}^{k-1}\lfloor \frac {a_i}{a_k}\rfloor a_k$,显然可以枚举 $d=\lfloor \frac {a_i}{a_k}\rfloor$ 的取值,然后根据区间 $[d\times a_k,(d+1)\times a_k)$ 中数值的个数计算贡献。 对于 $\sum_{i=1}^{k-1}\lfloor \frac {a_k}{a_i}\rfloor a_i$,一个暴力的想法是利用整数分块枚举 $d=\lfloor \frac {a_k}{a_i}\rfloor$,然后根据区间 $[d\times a_k,(d+1)\times a_k)$ 中数值的和计算贡献。 询问次数 $O(n\log n+n\sqrt v)$,于是总时间复杂度 $O\left(n\log^2 n+n\sqrt v\log2 v\right)$。非常卡常,据说能过,但我没过。 const int MAXN=2e5+5,MAXM=3e5+5; struct BIT{ #define lowbit(x) ((x)&(-x)) LL c[MAXM]; void add(int pos,int v){ while(pos === 优化一 === 不难发现查询次数是 $O(n\sqrt v)$,更新次数是 $O(n)$。考虑利用分块构造 $O(1)$ 查询 $O(\sqrt v)$ 更新的数据结构。 具体的,$O(\sqrt v)$ 维护每个块内部的前缀和以及所有块的前缀和,即可支持 $O(1)$ 查询。总时间复杂度 $O(n\sqrt v)$。 const int MAXN=2e5+5,MAXM=3e5+5,S=600; struct BIT{ #define lowbit(x) ((x)&(-x)) LL c[MAXM]; void add(int pos,int v){ while(pos=S) ans+=s2[pos/S-1]; return ans; } LL query(int L,int R){ return query(R)-query(L-1); } void update(int pos,int v){ int idx=pos/S; _for(i,pos%S,S) s1[idx][i]+=v; _for(i,idx,S) s2[i]+=v; } int main() { int n=read_int(); _for(i,0,n)a[i]=read_int(); LL ans=0,pre=0; _for(i,0,n){ ans+=pre; for(int j=1;a[i]*j === 优化二 === 对于 $\sum_{i=1}^{k-1}\lfloor \frac {a_k}{a_i}\rfloor a_i$,提前处理好 $a_i$ 对值域的贡献。 具体的,对 $[d\times a_i,(d+1)\times a_i)$,$a_i$ 的贡献为 $d\times a_i$。于是更新次数 $O(\log v)$,查询次数 $O(1)$,时间复杂度 $O(n\log^2 v)$。 const int MAXN=2e5+5,MAXM=3e5+5; struct BIT{ #define lowbit(x) ((x)&(-x)) LL c[MAXM]; void add(int pos,int v){ while(pos