>description
一條狹長的紙帶被均勻劃分出了 n 個格仔,格仔編號從 1 到 n。每個格仔上都染了一種顏色colori(用[1,m]當中的乙個整數表示),並且寫了乙個數字numberi。
定義一種特殊的三元組:(x,y,z),其中x,y,z都代表紙帶上格仔的編號,這裡的三元組要求滿足以下兩個條件:
1.x,y,z都是整數, x>input
第一行是用乙個空格隔開的兩個正整數 n 和 m,n 代表紙帶上格仔的個數,m 代表紙帶上 顏色的種類數。
第二行有 n 個用空格隔開的正整數,第 i 個數字numberi代表紙帶上編號為 i 的格仔上面寫的數字。
第三行有 n 個用空格隔開的正整數,第 i 個數字colori代表紙帶上編號為 i 的格仔染的顏色。
>output
共一行,乙個整數,表示所求的紙帶分數除以 10,007 所得的餘數。
>sample input
6 25 5 3 2 2 2
2 2 1 1 2 1
>sample output
82對於第 1 組至第 2 組資料,1 ≤ n ≤ 100, 1 ≤ m ≤ 5;
對於第 3 組至第 4 組資料,1 ≤ n ≤ 3000, 1 ≤ m ≤ 100;
對於第 5 組至第 6 組資料,1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000,且不存在出現次數超過 20 的顏色;
對於全部 10 組資料, 1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000, 1 ≤ colori ≤ m, 1 ≤ numberi ≤ 100000。
>解題思路
這一道題看著就很dp,所以我們試著做一下dp
看過題目,我們可以發現,y
yy沒有什麼用,只要滿足z−x
z-xz−
x是乙個偶數,及col
or[x
]=co
lor[
z]color[x]=color[z]
color[
x]=c
olor
[z]就行了
設f [i
]f[i]
f[i]
為到i
ii為止的答案,可以打出乙個o(n^2),但是這樣還不是正解
假設當前數為z,我們來從x轉移答案
看一下答案的求法:(x+
z)∗(
numx
+num
z)(x + z) ∗ (numx + numz)
(x+z)∗
(num
x+nu
mz)把它簡化一下:x * numx + x * numz + z * (numx + numz)
我們只需要維護一下這四個數(numz為numz*x的數量)
s[i]為x總數,sum[i]為num[x]的和,t[i]為x序號的和,f[i]為x序號 * a[x]的和(自己推一下)
a ns
=num
z∗t+
f+z∗
(sum
+s∗n
umz)
ans=numz*t+f+z*(sum+s*numz)
ans=nu
mz∗t
+f+z
∗(su
m+s∗
numz
) 然後就打出了乙個90分的方法,有乙個點tle了
for
(int i =
3; i <= n; i++
)}
因為z是偶數時只考慮偶數的x,是奇數時只考慮奇數的x
所以我們可以把每乙個顏色中的偶數和奇數分組,這樣就可以o(1)轉移了tt
>**
#include
#include
#include
#include
#define p 10007
#define n
100005
#define int long long
using namespace std;
int n, m, a[n]
, c[n]
, s[n]
[2], sum[n]
[2], t[n]
[2], f[n]
[2], ans;
signed main()
//很醜的碼
printf
("%lld"
, ans)
;return0;
}
數論 餘數求和
luogu p2261 cqoi2007 餘數求和 有的小夥伴看到這道題,第一感覺是這樣的 好簡單。這麼水一道題,不是有手就行?於是碼出了這樣一段 int n,k,ans intmain printf d n ans return0 但是很抱歉的是,只能過乙個點。本題其實用到了整除分塊的一些推論以及...
數論分塊與求和計算公式
分兩種,一種是純公式推導,化簡成f i g i t i i 1 n ni f i g i t i sum n lfloor frac rfloor quad f i g i t i i 1 n in 除求和外其他式子能在o 1 的時間內求出來,然後分塊計算即可 另一種是使用分塊思想 一般是列舉約數,...
數論分塊與求和計算公式
分兩種,一種是純公式推導,化簡成f i g i t i i 1 n ni f i g i t i sum n lfloor frac rfloor quad f i g i t i i 1 n in 除求和外其他式子能在o 1 的時間內求出來,然後分塊計算即可 另一種是使用分塊思想 一般是列舉約數,...