1. 程式人生 > >【Solve summary】求和

【Solve summary】求和

using ons namespace 要求 種類 定義 ID sig 一個

【Problem description】

問題描述

一條狹長的紙帶被均勻劃分出了n個格子,格子編號從1到n。每個格子上都染了一種顏色color_i(用[1,m]當中的一個整數表示),並且寫了一個數字number_i。

  定義一種特殊的三元組:(x,y,z),其中x,y,z都代表紙帶上格子的編號,這裏的三元組要求滿足以下兩個條件:
  xyz是整數,x<y<z,y-x=z-y colorx=colorz  

滿足上述條件的三元組的分數規定為(x+z)*(number_x+number_z)。整個紙帶的分數規定為所有滿足條件的三元組的分數的和。這個分數可能會很大,你只要輸出整個紙帶的分數除以10,007所得的余數即可。

【Input format】

第一行是用一個空格隔開的兩個正整數n和m,n表紙帶上格子的個數,m表紙帶上顏色的種類數。
  第二行有n用空格隔開的正整數,第i數字number表紙帶上編號為i格子上面寫的數字。
  第三行有n用空格隔開的正整數,第i數字color表紙帶上編號為i格子染的顏色。

【Output format】

共一行,一個整數,表示所求的紙帶分數除以10,007所得的余數。

【Algorithm design】

Simple enumeration + Mathematics deal

【Problem analysis】

Consequent不可取

Mathematics思維

核心:數據分離

N太大 直接搞O(N2)

讀題

x<y<z,y-x=z-y,colorx=colorz
翻譯一下

x,z奇偶性相同且同種顏色

那麽把n拆成兩條鏈

奇數鏈

偶數鏈

兩鏈互不相幹

對於鏈上所有同種顏色的點 都可以求分數

既然如此再看

(x+z)*(number_x+number_z)

拆解後

x*num_x+z*num_z+x*num_z+z*num_x

前綴和思想

取一點x 那麽關於x的所有三元組的分數之和

x*num_x*cnt_others + sumcnt_others + x*numcnt_others + num_x*idcnt_others

所以只需要分兩條鏈

枚舉每個點

根據其顏色進行處理

O(2n)

Anyway

把cnt處理完了再搞會有一倍冗出

所以邊枚舉邊搞最好

先前忘了這點楞了幾分鐘

錯誤記錄

沒把ans求余

沒考慮sum也很大也要求余

即使執行上述操作 sum還是很大

LL型適配

【Source code】

#include <bits/stdc++.h>

#define F(i,j,k) for(int i=j;i<=k;i++)

#define D(i,j,k) for(int i=j;i>=k;i--)

#define sc(i) scanf("%lld",&i)

#define mo 10007

#define ll long long

#define R return

using namespace std;

int n,m;

ll ans,num[100010],col[100010],sumnu[100010],sum[100010],sumid[100010],cnt[100010];

void read()

{

cin>>n>>m;

F(i,1,n)sc(num[i]);

F(i,1,n)sc(col[i]);

R;

}

void work()

{

F(jff,1,2)

{

memset(sumid,0,sizeof(sumid));

memset(sumnu,0,sizeof(sumnu));

memset(sum,0,sizeof(sum));

memset(cnt,0,sizeof(cnt));

for(int i=jff;i<=n;i+=2)

{

ans=(ans+sum[col[i]]+num[i]*i*cnt[col[i]])%mo;

ans=(ans+sumnu[col[i]]*i)%mo;

ans=(ans+sumid[col[i]]*num[i])%mo;

sumid[col[i]]=(sumid[col[i]]+i)%mo;

sumnu[col[i]]=(sumnu[col[i]]+num[i])%mo;

sum[col[i]]=(sum[col[i]]+num[i]*i)%mo;

cnt[col[i]]++;

}

}

cout<<ans<<endl;

R;

}

int main()

{

freopen("sum.in","r",stdin);

freopen("sum.out","w",stdout);

read();

work();

R 0;

}

【Solve summary】求和