原题链接
题目
思路
- 本题最重要的一点在于要注意观察到数据范围,说明肯定有数是重复出现多次的
- 考虑哈希,记录每个数出现的次数
- 对于两个不同数,他们根据题目要求总共可以组成 c n t a ∗ c n t b cnt_a * cnt_b cnta∗cntb 个相同组合
- 对于两个相同数,他们根据题目要求总共可以组成 ( 1 + c n t a ) ∗ c n t a / 2 (1 + cnt_a) * cnt_a / 2 (1+cnta)∗cnta/2 个相同组合【参考那个首相加末项的公式】。
- 注意开 l o n g l o n g longlong longlong
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int n;
cin >> n;
map<int, int> ma;
for (int i = 1; i <= n; i ++ )
{
int x;
cin >> x;
ma[x] ++;
}
int sum = 0;
for (int i = 0; i <= 1000; i ++ )
{
for (int j = i; j <= 1000; j ++ )
{
int add;
if (i == j) add = (1 + ma[i]) * ma[i] / 2;
else add = ma[i] * ma[j];
sum += abs(i + j - 1000) * add;
}
}
cout << sum << endl;
return 0;
}
总结
赛时其实想到了数据范围,可是接着就想到了用set做,总之就是再瞎绕弯子,赛时还是需要注意心态的,否则简单的题目都做不出来。
贴一个赛时错误代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
set<int> s;
unordered_map<int, int> ma;
int n;
cin >> n;
for (int i = 1; i <= n; i ++ )
{
int x;
cin >> x;
ma[x] ++;
s.insert(x);
}
int sum = 0;
for (auto i : s)
{
for (int j : s)
{
if (i == j)
{
sum = sum + abs(i + j - 1000) * (ma[i] * (ma[i] - 1));
}
else
{
sum = sum + abs(i + j - 1000) * (ma[i] * ma[j] );
}
}
}
cout << sum << endl;
return 0;
}