zoukankan      html  css  js  c++  java
  • CF1553F Pairwise Modulo 题解

    Codeforces
    Luogu

    Description.

    对每个 \(k\)

    \[\sum_{i=1}^k\sum_{j=1}^ka_i\ \text{mod}\ a_j \]

    Solution.

    因为这个相当于是求一个前缀的权值,所以我们考虑一个一个插入元素。
    考虑插入一个元素后多出来了什么,显然多出来了两部分。

    \[\left(\sum_{j=1}^{i-1}a_j\ \text{mod}\ a_i\right)+\left(\sum_{j=1}^ia_i\ \text{mod}\ a_j\right) \]

    由于 \(a_i\ \text{mod}\ a_j=0\),所以重复的那个可以不需要考虑。
    然后根据经典套路,考虑把 \(x\ \text{mod}\ y\) 变成 \(x-y\times\left\lfloor\frac xy\right\rfloor\)
    然后带入式子后发现,式子变成了

    \[\begin{aligned} \left(\sum_{j=1}^{i-1}a_j\right)-\left(\sum_{j=1}^{i-1}{\left\lfloor\frac{a_j}{a_i}\right\rfloor}\times a_j\right)+\left(a_i\times (i-1)\right)-\left(\sum_{j=1}^{i-1}\left\lfloor\frac{a_i}{a_j}\times a_j\right\rfloor\right) \end{aligned} \]

    接下来就考虑如何算式子了。
    第一部分和第三部分就不说了,直接求和有手就行。
    然后第二部分就是一个根号分治,小于根号开桶,大于根号暴算,复杂度 \(O(n\times\sqrt v)\)
    然后第四部分就直接一个整除分块,然后用一个数据结构维护前缀和。
    注意查询有 \(O(n\times\sqrt v)\) 次,而修改只有 \(O(n)\) 次,如果用树状树组等 \(O(\log)-O(\log)\) 的数据结构复杂度不平衡。
    可以考虑值域分块,复杂度 \(O(\sqrt v)-O(1)\),这样复杂度平衡,可以优化掉一个 \(\log\)
    然后这题就做完了,我也不知道为什么昨晚降智不会做。

    Coding.

    点击查看不行代码
    //是啊……你就是那只鬼了……所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<'0'||c>'9';c=getchar()) if(c=='-') f=1;
    	for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	if(f) x=-x;
    }/*}}}*/
    const int N=300000,B=550,blt=N/B+5;
    int n,cb[blt+5],ca[N+5];ll sb[blt+5],sa[N+5],vl[blt+5],res=0;
    inline int qryc(int x) {x=min(x,N);return cb[(x-1)/B+1]+ca[x];}
    inline ll qrys(int x) {return sb[(x-1)/B+1]+sa[x];}
    inline void modif(int x)
    {
    	int wh=(x-1)/B+1;for(int i=wh+1;i<=blt;i++) cb[i]++,sb[i]+=x;
    	for(int i=x;i<=min(N,wh*B);i++) ca[i]++,sa[i]+=x;
    	for(int i=1;i<=B;i++) vl[i]+=x/i;
    }
    int main()
    {
    	read(n);for(int i=1,x;i<=n;printf("%lld ",res),modif(x),i++)
    	{
    		read(x),res+=1ll*(i-1)*x;//ai mod ? = ai * x - \sum ai / ? * ?
    		for(int l=1,r;l<=x;l=r+1) r=x/(x/l),res-=1ll*(qrys(r)-qrys(l-1))*(x/l);
    		res+=qrys(N);if(x<=B) res-=vl[x]*x;else//? mod ai
    			for(int i=x;i<=N;i+=x) res-=1ll*i*(qryc(i+x-1)-qryc(i-1));
    	}
    	return putchar('\n'),0;
    }
    
  • 相关阅读:
    C语言温习杂记
    C语言变量类型与内存管理
    解析搜狗新闻语料库
    关于clang, scan-build, 和clang test
    Clang checker类总结
    让你的checker出现在clang的checker list中
    Clang安装配置解释
    Operators 操作
    cumulative_distribution累积分布
    SVM
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15048638.html
Copyright © 2011-2022 走看看