传送门
文章目录
- 题意
- 思路:
题意
给定一个不同数组成的序列aaa,定义pkp_kpk为pk=∑i=1k∑j=1kaimodajp_k=\sum_{i=1}^k\sum_{j=1}^ka_i\bmod a_jpk=∑i=1k∑j=1kaimodaj,让你对于每个i∈[1,n]i\in [1,n]i∈[1,n]求出pip_ipi。
2≤n≤2e5,1≤ai≤3e52\le n\le 2e5,1\le a_i\le 3e52≤n≤2e5,1≤ai≤3e5
思路:
考虑每次新增了什么,不难发现从pi−1p_{i-1}pi−1到pip_ipi新增了∑j=1iaimodaj+∑j=1iajmodai\sum_{j=1}^i a_i\bmod a_j+\sum_{j=1}^ia_j\bmod a_i∑j=1iaimodaj+∑j=1iajmodai。
对于这俩式子的不取模的时候贡献,第一个是查询[1,i−1][1,i-1][1,i−1]中大于aia_iai的值的个数再乘上aia_iai,第二个是查询[1,i−1][1,i-1][1,i−1]中小于aia_iai的值的和。
对于第二个式子,aia_iai固定,我们考虑枚举aia_iai的倍数,对应[0,ai),[ai,2∗ai),...[0,a_i),[a_i,2*a_i),...[0,ai),[ai,2∗ai),...,我们还是查询区间和,让后减去k∗aik*a_ik∗ai即可,其中kkk是有几个aia_iai。
对于第一个,我们考虑将其化简一下,aimodaj=ai−aj∗⌊aiaj⌋a_i\bmod a_j=a_i-a_j*\left \lfloor \frac{a_i}{a_j} \right \rflooraimodaj=ai−aj∗⌊ajai⌋,对于后面的下取整的式子我们显然可以直接整除分块,但是这样会t掉。。
直接考虑贡献不好弄,我们考虑对于每个aia_iai,我们将其对其他数的贡献存下来,也就是我们依旧枚举aia_iai的倍数,将ai,2∗ai,...a_i,2*a_i,...ai,2∗ai,...的位置都加上aia_iai,此时只需要查询[1,ai][1,a_i][1,ai]的和即可,贡献都已经放到里面了。
// Problem: F. Pairwise Modulo
// Contest: Codeforces - Harbour.Space Scholarship Contest 2021-2022 (open for everyone, rated, Div. 1 + Div. 2)
// URL: https://codeforces.com/problemset/problem/1553/F
// Memory Limit: 256 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=600010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int n;
int a[N];
struct BIT {LL tr[N];#define lowbit(x) (x&(-x))void add(int x,int c) {while(x<N) tr[x]+=c,x+=lowbit(x);}LL sum(int x) {if(x<=0) return 0ll;LL ans=0;// while(x) ans+=tr[x],x-=lowbit(x);for(int i=x;i;i-=lowbit(i)) ans+=tr[i];return ans;}}tr1,tr2,tr3;int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);LL ans=0,mx=*max_element(a+1,a+1+n);for(int i=1;i<=n;i++) {for(int j=0,k=a[i]-1;k<=mx*2;j++,k+=a[i]) {LL all=tr1.sum(k)-tr1.sum(max(k-a[i],0));ans+=all;ans-=1ll*j*a[i]*(tr2.sum(k)-tr2.sum(max(k-a[i],0)));}ans+=1ll*a[i]*(i-1);ans-=tr3.sum(a[i]);for(int j=a[i];j<=mx;j+=a[i]) tr3.add(j,a[i]);// for(int l=1,r;l<=a[i];l=r+1) {// r=a[i]/(a[i]/l);// int now=a[i]/l;// ans-=1ll*now*(tr1.sum(r)-tr1.sum(l-1));// }tr1.add(a[i],a[i]);tr2.add(a[i],1);printf("%lld ",ans);}puts("");return 0;
}
/**/