题目:
见https://www.luogu.com.cn/problem/P2671
我的思路:
本菜鸡只会暴力(没有那么暴力,但是还是超时了3个测试样例),见代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long LL;
const int N=100010;
const int mod=10007;
struct A
{
int id,number,color;
};
A Data[N];
bool cmp(A a,A b)
{
return a.color<b.color;
}
LL res=0;
int main()
{
int n,m;
while(cin>>n>>m)
{
for(int i=1;i<=n;i++)
{
Data[i].id=i;
cin>>Data[i].number;
}
for(int i=1;i<=n;i++)
cin>>Data[i].color;
sort(Data+1,Data+n+1,cmp);//按颜色排序了
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
int temp=Data[i].id+Data[j].id;
if(Data[i].color==Data[j].color&&temp%2==0)
{
res+=(((Data[i].id+Data[j].id)%mod)*((Data[i].number+Data[j].number)%mod))%mod;//
res%=mod;//这两个位置取模很关键
}
else if(Data[i].color!=Data[j].color)//这个else if也很关键不然我估计只能得30分
break;
}
cout<<res<<endl;
res=0;//清零别忘了!!!
}
return 0;
}
大佬的思路:
https://www.luogu.com.cn/blog/ShanXian/solution-p2671
强的一:
复制黏贴来的关键思路
我们可以用一下分组思想,把每个颜色分为一组,再在每个颜色中按奇偶分组,所以一共有2m组
设一个分组里有k个数,这个分组中的数分别是x[1],x[2]……x[k],下标分别是y[1],y[2]……y[k]
那么可得
答案=(x[1]+x[2])(y[1]+y[2])+(x[1]+x[3])(y[1]+y[3])+……+(x[1]+x[k])*(y[1]+y[k])
+(x[2]+x[3])(y[2]+y[3])+(x[2]+x[4])(y[2]+y[4])+……+(x[2]+x[k])*(y[2]+y[k])
+……
+(x[k-1]+x[k])*(y[k-1]+y[k])
=x[1]*(y[1]+y[2]+y[1]+y[3]+……+y[1]+y[k])
+x[2]*(y[1]+y[2]+y[2]+y[3]+……+y[2]+y[k])
+……
+x[k]*(y[1]+y[k]+y[2]+y[k]+……+y[k-1]+y[k])
=x[1]*(y[1]*(n-2)+y[1]+y[2]+……+y[k])
+x[2]*(y[2]*(n-2)+y[1]+y[2]+……+y[k])
+……
+x[k]*(y[k]*(n-2)+y[1]+y[2]+……+y[k])
然后事先将y[1]+y[2]+……+y[k]求出,用的时候调用就行了,其时间复杂度为O(n)
大佬的代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N=100010;
const int mod=10007;
int res;
int main()
{
int n,m;
while(cin>>n>>m)
{
int s[N][2],sum[N][2],c[N],x[N];//为啥开2呢,为了直接区分奇数组偶数组
for(int i=1;i<=n;i++)
cin>>x[i];
for(int i=1;i<=n;i++)
{
cin>>c[i];
s[c[i]][i%2]++;//每组元素的个数
sum[c[i]][i%2]=(sum[c[i]][i%2]+x[i])%mod;//提前算出总和
}
for(int i=1;i<=n;i++)
{
res=(res+i*((s[c[i]][i%2]-2)*x[i]%mod+sum[c[i]][i%2]%mod))%mod;
}
cout<<res<<endl;
res=0;//res记得归零,或者不用全局变量
}
return 0;
}