CF1553F Pairwise Modulo
分两种情况讨论
- \(a_i\bmod a_j\)
- \(a_i < a_j\)
那么 \(a_j\) 对答案的贡献是 \(a_i\)。
- \(a_i > a_j\)
那么 \(a_j\) 对答案的贡献是 \(a_i-a_j \times \lfloor \dfrac{a_i}{a_j} \rfloor\),和第一个合并一下就是 \(a_i \times (i-1) - \lfloor \dfrac{a_i}{a_j} \rfloor\)。
后面的这部分可以转化为枚举一个 \(l\),在区间 \([a_j \times l,a_j \times (l+1) -1]\) 上加上 \(a_j \times l\),这个可以用树状数组维护。
- \(a_j \bmod a_i\)
- \(a_j<a_i\)
贡献为 \(a_j\)。
- \(a_j>a_i\)
贡献为 \(a_j-a_i \times \lfloor \dfrac{a_j}{a_i} \rfloor\),和第一种情况同理,前面一部分贡献为 \(\sum a_j\),后面同上一种情况,对于区间 \([a_i \times l,a_i \times (l+1) -1]\) 上减去上 \(a_j\) 在这个区间里的个数乘上 \(a_j \times l\),同样可以用树状数组维护。
时间复杂度为 \(O(n \log^2 n)\)。
#include <bits/stdc++.h>
#define reg register
#define fi first
#define se second
#define mp std::make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
ll rd()
{
reg ll x=0,f=0;
reg char ch=getchar();
while(!isdigit(ch)) (ch=='-')&&(f=1),ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
#define int long long
const int MAXN=2e5+10;
const int MAXM=3e5+10;
int n,a[MAXN];
int c[MAXM][2];
// 0:val 1:num
void add(reg int x,reg int v,reg int op)
{
for(;x<MAXM;x+=(x&(-x))) c[x][op]+=v;
}
int qry(reg int x,reg int op)
{
reg ll ret=0;
for(;x;x-=(x&(-x))) ret+=c[x][op];
return ret;
}
void work()
{
n=rd();
for(reg int i=1;i<=n;++i) a[i]=rd();
int sum=0,ans=0;
for(reg int i=1;i<=n;++i)
{
ans+=sum+1ll*a[i]*(i-1)-qry(a[i],0);
sum+=a[i];
for(reg int j=a[i];j<MAXM;j+=a[i])
{
ans-=j*(qry(std::min(j+a[i]-1,MAXM-1),1)-qry(j-1,1));
add(j,j,0),add(std::min(j+a[i]-1,MAXM-1)+1,-j,0);
}
add(a[i],1,1);
printf("%lld ",ans);
}
puts("");
}
#undef int
int main()
{
int _=1;
// _=rd();
while(_--) work();
return 0;
}