At356 E - Max/Min
E.Max/Min
题意简述
给你一个长为 \(N\)的序列 \(A=(A_1,\ldots,A_N)\) .
计算 \(\displaystyle \sum_{i=1}^{N-1}\sum_{j=i+1}^{N}\left\lfloor\frac{\max(A_i,A_j)}{\min(A_i,A_j)}\right\rfloor\).
[]是向下取整的意思
解题思路
因为\(a_i\)值域非常的小,只有1e6,考虑桶存,又因为计算整除,考虑调和级数的枚举方案,
具体做法,枚举每个数的倍数,计算 $ \sum_{s=1}^{N} \sum_{t=1}^{N} \left\lfloor \frac{A_s}{A_t} \right\rfloor$,但是由于对于单个数这样计算的值是 \(cnt[n]·cnt[n]\) 实际我们需要的是 \(cnt[n]·(cnt[n]-1)/2\) 因此多计算了 \(cnt[n]·(cnt[n]+1)/2\),其中\(cnt\) 表示某个数的出现次数
AC code
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N=1e6;
ll cnt[N+1];
int main(){
cin.tie(0)->ios::sync_with_stdio(false);
int n;cin>>n;
for(int i=1,x;i<=n;i++) cin>>x,cnt[x]++;
for(int i=1;i<=N;i++) cnt[i]+=cnt[i-1];
ll ans=0;
for(int i=1;i<=N;i++){
if(cnt[i]-cnt[i-1]==0) continue;
ll x=cnt[i]-cnt[i-1];
ans-=x*(x+1)/2;
for(int j=i;j<=N;j+=i){
int r=min(j+i-1,N);
int l=j-1;
ans+=(cnt[r]-cnt[l])*x*(j/i);
}
}
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号