补题 abcE - Max/Min 前缀和
作者:
多米尼克領主的致意
,
2024-06-03 20:30:13
,
所有人可见
,
阅读 9
这题关键在于
Ai的范围(1, 1e6)
可以开出这么大的数组
思路:
1.分为数对两数相同和不同
2.相同就是求2个组合数
3.不同的按此数为较小数枚举 每次枚举的区间[j, 2 * j - 1]除以此数的下取整
这个值是相同的 因此可以用前缀和计数 把i = j到1e6之间形如[j, 2 * j - 1]的区间的贡献累加
tip:
前缀和乘的时候要除去i自己
右区间不能大于1e6 要取min
时间复杂度O(n*n/ai)
code:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, INF = 1e6;
typedef long long ll;
ll a[INF + 10], s[INF + 10];
// set<int>h;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
for(int i = 1;i <= n;i++){
int x;
cin >> x;
a[x]++;
}
for(int i = 1;i <= INF;i++){
// cout << "1\n";
s[i] = s[i - 1] + a[i];
// cout << s[i] << endl;
}
ll ans = 0;
for(int i = 1;i <= INF;i++){
ans += a[i] * (a[i] - 1) / 2;
for(int j = i;j <= INF;j += i){
ans += a[i] * (ll)(j / i) * (s[min(INF, j + i - 1)] - s[(i == j) ? i : j - 1]);
}
}
cout << ans << endl;
return 0;
}