传送门
分析
-
40 pts : (O(n^2))
将原先的 (y-x = z-y) 化为 (2 imes y = x + z) ,只要暴力枚举 (x,z) 即可 -
100 pts: (O(n))
通过 40 分的做法,我们可以发现,对于一个符合要求的 (y) ,必须要 (x,z) 保持同号
那么我们不妨可以假设存在集合 (A) ,是得该集合内的所有元素(方格)为同种颜色,且符号相同的
于是,我们可以整理出这么一个式子:对于集合内的元素 (x_i) ,有 ((x_1 + x_2) * (num_1+num_2) + (x_1+x_3)*(num_1+num_3)+ …… +(x_1+x_n)*(num_1+num_n)+……+(x_{n-1}+x_n)*(num_{n-1}+num_{n}))
对于这个毫无规律的式子,我们可以先研究它的所有包含 (x_1) 的项,将其全部提出,可得 (i_1*num_1 + i_1*num_2 +i_1*num_1+i_1*num_3+……+i_1*num_1+i_1*num_n)
进一步合并为 (i_1*num_1*(n-1)+i_1*(num_2+num_3+num_4+……+num_n))
那么:我们可以归纳出这样一个式子:假设该种集合中共有 (k) 项,对于第 (n) 项,有 (i_n*num_n*(k-1)+i_n*(num_1+num_2+……+num_{n-1}+num_{n+1}+……+num_{k}))
对于这一串式子,可以先将其加上一个 (i_n*num_n),再减去一个 (i_n*num_n)
即为:(i_n*num_n*(k-2)+i_n*(num_1+num_2+……+num_{n-1}+num_n+num_{n+1}+……+num_{k}))
对于 ((num_1+num_2+……+num_{n-1}+num_n+num_{n+1}+……+num_{k})),我们可以直接前缀和处理得到
源代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
#define ll long long
using namespace std;
const ll mod=10007;
const ll maxn=1e5+10;
ll n,m,ans;
ll sum1[maxn][2];
ll sum2[maxn][2];
struct node
{
ll num,c;
} s[maxn];
int main(void)
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&s[i].num);
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&s[i].c);
sum1[s[i].c][i%2]++;
(sum2[s[i].c][i%2]+=s[i].num)%=mod;
}
for(int i=1;i<=n;i++)
{
(ans+=(i*((sum1[s[i].c][i%2]-2)*s[i].num+sum2[s[i].c][i%2])))%=mod;
}
printf("%lld
",ans);
return 0;
}