

题目要求我们计算所有满足条件的三元组总分,仔细观察三元组所需要满足的第一个条件:x < y < z, y - x = z - y,我们可以化为x + z = 2y,而三元组需要满足的第二个条件中不包含y,所以不难发现第一个条件可以转化为x + z为偶数。题目就转化为了寻找下标(从1开始)之和为偶数并且颜色相同的两个数,这样的两个数一定满足三元组的两个条件,将x,z(找到的两个数的下标)代入题目表达式,将所有结果相加就得到了答案。
所以我们只需要将所以颜色相同的数存放到一起,再从中找出所有符合上述条件数就可以了。这里可以使用map来将所有颜色相同的数存放到一起:
int co[100005]; // co代表该位置的颜色
map<ll, vector<ll>> mp;
for (int i = 1; i<= n; i++){
cin >> co[i];
mp[co[i]].push_back(i);
}
我们就可以将颜色相同的下标存放到同一个vector当中,后续需要访问就可以直接进行遍历。

再观察题目数据范围,使用双重循环来读取每一对数字的时间复杂度O()肯定会超时。我们可以先列举部分情况来观察是否具有某种规律:
假设总共有2种颜色(ai表示下标,a2表示下标为2):
颜色1:a1,a2,a3,a5。
颜色2:a4,a6。
对于颜色1:总和为(a1 + a3) * (num1+num3) + (a1 + a5) * (num1 + num5) + (a3 + a5) * (num3 + num5) = a1 * (num1 + num2 +num3) + a3 * (num1 + num2 +num3) + a5 * (num1 + num2 +num3) + a1 * num1 + a3 * num3 +a5 * num5;
对于颜色2:总和为(a4 + a6) * (num4 + num6) = a4 * (num4 + num6) + a6 * (num4 + num6);
相加为偶数有两种情况:奇 + 奇 / 偶 + 偶。所以对于相同颜色,我们可以对其中的所有元素分奇偶讨论。对于上述颜色1,(num1 + num2 +num3)为奇数和,所以总和为a1 * sum1(奇数和) + a3 * sum1 + a5 * sum1 + a1 * num1 + a3 * num3 + a5 * num5,其实只需要在颜色1中再加入几个几个奇数就可以更加明显的得出后半部分的规律(留下思考余地),后面部分其实是(奇数个数 - 2) * ai * numi,然后相加。所以可以得出:对于某种颜色,将其中的所有元素分奇偶单独存储,对所有的奇数进行遍历,ans(总分) += (ai * sum1(奇数和) % mod + (奇数个数 - 2) * ai * numi % mod),偶数操作相同。对所有颜色进行相同操作即可得到最后答案(注意取模)。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 6;
int num[N], co[N];
int mod= 1e4 +7;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n, m;
cin >> n >> m;
ll ans = 0;
for (int i = 1; i <= n; i++){
cin >> num[i];
}
map<ll, vector<ll>> mp;
for (int i = 1; i<= n; i++){
cin >> co[i];
mp[co[i]].push_back(i);
}
for (auto x : mp){
auto v = x.second;
vector<int> a, b;
ll sum1=0, sum2=0;
for (int i = 0; i < v.size(); i++){
if (v[i] % 2){
a.push_back(v[i]);
sum1 += num[v[i]];
} else{
b.push_back(v[i]);
sum2 += num[v[i]];
}
}
for (auto y : a){
ans += ((a.size() - 2) * y * num[y] + y * sum1) % mod;
ans %= mod;
}
for (auto y : b){
ans += ((b.size() - 2) * y * num[y] + y * sum2) % mod;
ans %= mod;
}
}
cout << ans;
return 0;
}
文章讲述了如何解决NOIP2015普及组的一道题目,通过将三元组条件转化为寻找颜色相同且下标和为偶数的数对,利用map存储颜色相同的数,然后对奇偶性进行讨论,分别计算奇数和偶数的贡献,最后进行模运算得到总和。代码中展示了具体实现过程。

1178

被折叠的 条评论
为什么被折叠?



