傳送門
#define runinstance(x) delete new x
struct cheat1
};//在主函式中
if(n <= 1000) runinstance(cheat1);
這樣就能做到不呼叫就不占用空間,呼叫不會爆棧,多次呼叫不會記憶體洩露。(如果確實要多次呼叫,最好還是把迴圈寫裡面)
②對於25%的資料(p≤
107p ≤10
7且
p p
為質數)
可以求逆元了。先線性時間預處理逆元,然後直接邊乘邊除。
但是要注意!使用逆元時要先對原數求一次模,因為這是把原數作為陣列下標直接訪問的!
inv[back % mod] //記住 % mod
這種騙分法效果也不是特別好,實測還是有乙個點會超時。當然,如果之前那個地方忘記模,可能就少了25分了 qaq。
③對於20%的資料(n−
k≤10' role="presentation" style="position: relative;">n−k
≤10n−
k≤10)
乙個很正常的想法是把重疊部分算出來,然後再算兩邊的,發現兩邊其實可以用字首和(積,下文都用和代替)預處理,這樣就能把時間從o(
n2) o(n
2)
降到o(
n)o (n
)(好像在這裡沒有什麼大用處)。
④對於100%的資料
做到第③步騙分時,就能發現,好像可以用字首和唉。。。
於是我們索性不要任何重疊部分,直接以k為單位劃分成塊,每次算兩個塊,最後乙個塊單獨處理即可。
注意:這裡的字首和不是通過後面的「減」前面的,而是通過算了左邊的部分後再加上右邊的部分得出答案。
參考**
#define next(x) int(((long long)(x) * b + c) % d)
struct work
cnt = next(seql[k]);
seqr[1] = cnt;
for(int i = 2; i <= k; i++)
seql[k + 1] = 1;
for(int i = k - 1; i >= 1; i--)
seqr[0] = 1;
for(int i = 2; i <= k; i++)
for(int i = 1; i <= k; i++)
}int remain = n % k;
remain = remain ? remain : k;
seql[1] = cnt;
for(int i = 2; i <= k; i++)
cnt = next(seql[k]);
seqr[1] = cnt;
for(int i = 2; i <= remain; i++)
seql[k + 1] = 1;
for(int i = k - 1; i >= 1; i--)
seqr[0] = 1;
for(int i = 2; i <= remain; i++)
for(int i = 1; i <= remain + 1; i++)
cout << ans << endl;
}};
(對於100%的資料的敘述有些渣,但是由於這個思路很好懂,所以不再詳細闡述,細節可以參考一下參考**)
所以有什麼需要注意的地方呢?
①看到這種明顯o(
n)o (n
)規模的題目(一千萬哪),先想想騙分(廢話),然後考慮字首和這個化腐朽為神奇的思想。
②注意到了嗎?這道題其實是要卡long long的空間的(這份**空間和常數都有點大,如果有更強的勿噴),所以要注意強轉。(原題空間 233 mib)
字首和思想
乙個區間可以拆成兩個字首和,這是乙個很基本的思想。反過來,兩個字首和的關係可以由乙個區間表示。有時某些區間問題可以轉化為字首和問題繼而減少情況和狀態。例 魔術師的桌子上有n個杯子排成一行,編號為1,2,n,其中某些杯子底下藏有乙個小球,如果你準確地猜出是哪些杯子,你就可以獲得獎品。花費c ij元,魔...
jzoj 3789( 棧 字首和)
sample input8 i 2 i 1 i 1 q 3 l d r q 2 sample output2 3題意 正在設計一種新型的編輯器,這種編輯器可以高效地處理整數序列。編輯器啟動時,序列為空,游標指向序列的頭部。編輯器支援下列 5 種操作 1.i x 把整數 x 插入到游標位置 2.d 刪...
字首和 DP 登機(jzoj 5535)
有一架飛機,有n個人要登機,每個人的不滿值為登機時當前機艙在他所在行前方的人數總和,現在可以把飛機分為k個機艙,使不滿值總和最小 小h是機場登機的執行經理。他的工作是優化登機流程。飛機上的座位有s行,編號從1到s,每行有六個座位,標記為a到f。今天 有n個乘客陸續登機,第i名乘客的座位在第ri行,則...