D. Small GCD
题解
由于答案之和最小的两个数有关,所以我们可以把数组排序
然后遍历数组,对于第 \(i\) 个数,遍历其所有因子 \(k\),统计 \(i\) 前面有多少数与 \(a[i]\) 的 \(\gcd=k\)
实施
预处理所有数的因子,然后从大到小遍历,时间复杂度 \(O(nlogn^2)\)
code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[80005];
vector<ll> fac[100005];
ll f[100005]={0};
ll g[100005]={0};
void solve()
{
memset(f,0,sizeof f);
memset(g,0,sizeof g);
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
ll ans=0;
for(int i=1;i<=n;i++)
{
for(auto it:fac[a[i]])
{
f[it]=g[it];//g[it] 代表[1,i-1] 内,含有因子it 的个数
for(auto j:fac[a[i]/it])//为什么是fac[a[i]/it]?因为要排除 it*k,有的k不一定出现
{
if(j==1) continue;
f[it]-=f[it*j];
}
ans+=it*f[it]*(n-i);
g[it]++;
}
}
cout<<ans<<'\n';
}
int main()
{
for(int i=1e5;i>=1;i--)
{
for(int j=i;j<=1e5;j+=i) fac[j].push_back(i);
}
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
while(t--) solve();
return 0;
}

浙公网安备 33010602011771号