首页 > 技术文章 > P2671 [NOIP2015 普及组] 求和

guiyou 2021-07-16 08:18 原文

题解

定义一种特殊的三元组:(x,y,z),其中x,y,z都代表纸带上格子的编号,这里的三元组要求满足以下两个条件:

  1. x y z是整数,x<y<z,y-x=z-y
  2. colorx = colorz

通过第一个条件易得x,y一定是同奇同偶
第二个条件无非是在限制这个三元组中x,z颜色相同
(u1s1,这个玩意跟y貌似没什么关系,所以是二元组

满足上述条件的三元组的分数规定为(x+z)*(number_x+number_z)

题目的最终目标是计算所有三元组分数和

根据分数规定,纯模拟,直接TLE

细想其实这个三元组跟y没关系,所以只用考虑x,z

那么可以考虑把同奇同偶颜色相同的分为一组

如果此时再直接进行模拟,也还是会TLE

那么想想办法优化?

(x+z) * (number_x+number_z)=x * number_x+x *number_y+y * number_x+y * number_y
所以同一组内的分数
设m为组内的个数
组内第一个数所得得部分分数即
x * number_x+x *number_y

= i ∗ ∑ i = 2 m n u m [ i ] + ( n − 1 ) ∗ ( i ∗ n u m [ i ] ) i*\sum_{i=2}^mnum[i]+(n-1)*(i*num[i]) ii=2mnum[i]+n1(inum[i])
= i ∗ ∑ i = 1 m n u m [ i ] + ( n − 2 ) ∗ ( i ∗ n u m [ i ] ) i*\sum_{i=1}^mnum[i]+(n-2)*(i*num[i]) ii=1mnum[i]+(n2)(inum[i])
那么一个组的得分数
= ∑ i = 1 m ( i ∗ ∑ j = 1 m ∗ n u m [ j ] + ( m − 2 ) ∗ n u m [ i ] ) \sum_{i=1}^m(i*\sum_{j=1}^m*num[j]+(m-2)*num[i]) i=1m(ij=1mnum[j]+(m2)num[i])

∑ j = 1 m ∗ n u m [ j ] \sum_{j=1}^m*num[j] j=1mnum[j]这一部分可以再分组时用前缀和优化
时间复杂度即可达到O(n)

代码

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;
const int maxn=1e5+10;
int n,m;
int num[maxn];
long long sum[maxn][3];
int t[maxn][3];
const int mod=10007;
int c[maxn];
int main(){
	cin>>n>>m;memset(t,0,sizeof(t));
	for(int i=1;i<=n;++i) cin>>num[i]; 
	for(int i=1;i<=n;++i){
		cin>>c[i];
		t[c[i]][i%2]++;//记录组内个数
		sum[c[i]][i%2]=(sum[c[i]][i%2]+num[i])%mod;
	}long long ans=0;
	for(int i=1;i<=n;++i){
		ans=(ans+i*(sum[c[i]][i%2]+(t[c[i]][i%2]-2)*num[i]))%mod;
	}cout<<ans<<endl;
	return 0;
}
 

题目链接

P2671 [NOIP2015 普及组] 求和

推荐阅读