1. 程式人生 > 其它 >字首和:P2671 [NOIP2015 普及組] 求和

字首和:P2671 [NOIP2015 普及組] 求和

原題傳送門

因為三元組x,y,z是等差數列,所以x和z奇偶性一致,然後按照奇偶以及顏色分組

對於某種奇偶性的某種顏色:

答案=(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])

xk和每個yi乘了一遍,跟yk額外乘了k-2遍

然後就是O(n)的字首和了,先求出Σy即可

#include<bits/stdc++.h>
#define
N 100005 #define mod 10007 using namespace std; long long a[N],b[N],osum[N],esum[N]; vector<int> odd[N],even[N]; vector<int> oddn[N],evenn[N]; int main(){ long long n,m,i,j,x,ans; cin>>n>>m; for(i=1;i<=n;i++){ // scanf("%lld",&a[i]); cin>>a[i]; }
for(i=1;i<=n;i++){ cin>>x; // scanf("%lld",&x); if(i%2==1){ odd[x].push_back(a[i]); oddn[x].push_back(i); } else{ even[x].push_back(a[i]); evenn[x].push_back(i); } } for(i=1;i<=m;i++){ osum[i]
=0; for(j=0;j<odd[i].size();j++){ // printf("%d %d\n",odd[i][j],oddn[i][j]); osum[i]+=odd[i][j]; osum[i]%=mod; } // printf("---%d\n",osum[i]); esum[i]=0; for(j=0;j<even[i].size();j++){ // printf("%d %d\n",even[i][j],evenn[i][j]); esum[i]+=even[i][j]; esum[i]%=mod; } // printf("---%d\n",esum[i]); } ans=0; for(i=1;i<=m;i++){ if(odd[i].size()>=2) for(j=0;j<odd[i].size();j++){ // cout<<oddn[i][j]<<"*"<<(osum[i]+(n-2)*odd[i][j])<<endl; ans+=(oddn[i][j]*(osum[i]+(odd[i].size()-2)*odd[i][j])); ans%=mod; } if(even[i].size()>=2) for(j=0;j<even[i].size();j++){ ans+=(evenn[i][j]*(esum[i]+(even[i].size()-2)*even[i][j])); ans%=mod; } } cout<<ans; }