题解 P2671 【求和】
40分的的O(n^2)暴力:
#include<bits/stdc++.h>
#define ll long long
#define MOD 10007
using namespace std;
ll n,m,sum,number[100010],colour[100010];
int main(){
scanf("%lld %lld",&n,&m);
for(ll i=1; i<=n; i++) scanf("%lld",&number[i]);
for(ll i=1; i<=n; i++) scanf("%lld",&colour[i]);
for(ll i=1; i<=n; i++){//穷举x
for(ll j=i+1; j<=n; j++){//穷举y
ll k=2*j-i;//算出k
if(j<k){//i一定小于j,所以不用判断
if(colour[i]==colour[k]) sum=(sum+(i+k)*(number[i]+number[k]))%MOD;
}
}
}
printf("%lld",sum);
return 0;
}
60分的代码:
#include<bits/stdc++.h>
#define ll long long
#define MOD 10007
using namespace std;
ll n,m,sum,Prev[100010];
struct node{
ll number,colour,place;
}a[100010];
inline bool cmp(node a,node b){//按颜色和原位置排序
if(a.colour==b.colour) return a.place<b.place;
return a.colour<b.colour;
}
int main(){
scanf("%lld %lld",&n,&m);
for(ll i=1; i<=n; i++) scanf("%lld",&a[i].number);
for(ll i=1; i<=n; i++) scanf("%lld",&a[i].colour);
for(ll i=1; i<=n; i++) a[i].place=i;
sort(a+1,a+1+n,cmp);
for(ll i=1; i<=n; i++) Prev[a[i].place]=i;
for(ll i=1; i<=n; i++){//穷举x
for(ll k=i+1; k<=n; k++){//穷举z
if((a[i].place+a[k].place)%2==1) continue;
if(a[i].colour!=a[k].colour) break;
ll j=Prev[(a[i].place+a[k].place)/2];//算出j
if(a[i].place<a[j].place&&a[j].place<a[k].place) sum=(sum+(a[i].place+a[k].place)*(a[i].number+a[k].number))%MOD;
}
}
printf("%lld",sum);
return 0;
}
AC的代码:
本代码的关键在cmp函数
满足的条件:
1.xyz是整数,x<y<z,y-x=z-y
2.color[x]=color[z]
首先,(x+z)%2==0
那么,x和z的奇偶性相同
我们可以做一个排序,把这些东西排序起来,再穷举x和z并吸氧(O2优化),这样就过了!!!(一个点900ms-)
#pragma GCC optimize(2)//优化1:O2优化
#include<bits/stdc++.h>
#define ll long long
#define MOD 10007
using namespace std;
ll n,m,sum;
struct node{
ll number,colour,place;
//place代表原来的位置
}a[100010];
inline bool cmp(node a,node b){
//比较方式:
//1.按对2取余的结果从小到大
//2.按颜色,颜色相同的放在一起
//3.按位置从小到大
if(a.place%2==b.place%2){
if(a.colour==b.colour) return a.place<b.place;
return a.colour<b.colour;
}
return a.place%2<b.place%2;
}
int main(){
scanf("%lld %lld",&n,&m);
for(ll i=1; i<=n; i++) scanf("%lld",&a[i].number);
for(ll i=1; i<=n; i++) scanf("%lld",&a[i].colour);
for(ll i=1; i<=n; i++) a[i].place=i;
sort(a+1,a+1+n,cmp);
for(ll i=1; i<=n; i++){//穷举x
for(ll k=i+1; k<=n; k++){//穷举z
if((a[i].place+a[k].place)%2==1) break;//求和取余的值已经不为0,说明之后的值都不为0,直接跳出
if(a[i].colour!=a[k].colour) break;//颜色不同,跳出,理由同上
//话说为什么要求j呢……
sum=(sum+(a[i].place+a[k].place)*(a[i].number+a[k].number))%MOD;//数量增加
}
}
printf("%lld",sum);
return 0;
}