這篇博客主要是用來記本身寫代碼的時候犯的各類小技巧和低級失誤,好提醒本身,從而儘可能縮短debug時間。
點分治
1.求每個子樹到重心的距離的函數接口應該是dfs2(v, eg, e[i].w)
而不是dfs2(v, now, 0)
。一方面是子樹的父親是當前的重心,而不是進入這一層點分治的點;另外一方面別忘了考慮這條邊的貢獻。
2-SAT
1.建圖必定要考慮對稱性,即「若是\(x\)成立,則\(y\)必須成立」,那麼咱們還得考慮若是\(y\)不成立,則\(x\)也不能成立,好比[NOI2017]遊戲。
哈希
1.以爲有必要的話最好寫一個雙哈希,防止出題人卡天然溢出。
2取模版哈希在算子串哈希的時候也別忘了取模,要否則就有負數了。
3.哈希表是真的快!儘可能用哈希表代替map,防止被卡常。(好比[NOI2016]網格,剛開始用map有兩個點怎麼卡也卡不過去,改爲哈希表後只用了300多ms)
主席樹
1.查詢的時候,判斷是否往右走的條件是根據左區間而定,即t[t[now].ls].sum - t[t[old].ls].sum
,千萬別手滑寫成了t[now].sum - t[old].sum
。
線段樹
1.較複雜的線段樹通常須要推推式子才能知道要維護啥。推式子時有一個技巧,就是下標儘可能都保證是全局的編號,而不是某一個區間中的第幾個,這樣區間合併的時候每每會簡單的多,不用考慮兩個區間的左右關係,好比[HAOI2012]高速公路。
數論,數學
1.萬一遇到某一個題過程當中要求組合數卻不能取模,能夠嘗試取log,最後再用exp()
轉換成真正的值,好比HDU4254 A Famous Game。
2.求兩個數的lcm的時候爲了防止爆int或long long,要先除以gcd,再乘以另外一個數。
3.組合數必定要特盤\(m > n\)的狀況,尤爲是Lucas定理的時候!
lucas定理
1.在一篇博客上看到lucas定理能夠不用遞歸,而是每次把\(n\)和\(m\)都除以\(p\)直到0。有以下代碼html
In ll C(int n, int m) { if(n > m) return 0; return fac[n] * inv[n - m] % mod * inv[m] % mod; } In ll lucas(int n, int m) { if(m > n) return 0; ll ret = 1; for(; m; n /= mod, m /= mod) ret = ret * C(n % mod, m % mod) % mod; return ret; }
高斯消元
1.對於每一次的主元,咱們要找最大的數那一行,爲了減少偏差。不是最小的!
SAM
1.關於求每個節點的endpos數量:插入的時候標記這個節點是一個結束位置,最後咱們從下往上遞歸加一遍,就是每個的endpos數量。有好長一段時間我都覺得子樹大小=endpos數量。後來才忽然想明白,克隆出的節點的初值是0,由於他不是一個結束位置,因此咱們求出來的每個節點的endpos數量不等於子樹大小。
高精度
1.高精乘低精是先乘再進位!先進位再乘還得有點別的運算。(很久不寫調了半天,還看了我之前的博客)
雜項
1.assert()
是一個debug用的好東西,當括號裏的條件不成立時,會當即中止運行,並給出提示(在高級的oj上會告訴你),包含在<assert.h>
庫裏。
2.離散化數組必定要算好空間:好比把一堆區間離散化,就要開二倍。由於每個區間的左右端點都要算進去。
3.看到異或,第一反應是每一位單獨考慮!
4.clock()
是clock_t數據類型,返回的是long int。因此要是想保證程序運行時間小於0.9秒的話,必須強制轉換成double,即if((double)clock() / CLOCKS_PER_SEC) < 0.9
(CLOCKS_PER_SEC類型也是long int)。
5.參見上一條,咱們能夠在程序開始的時候寫一個double Beg = clock()
,結束的時候寫一個doube End = clock()
,這樣輸出(End - Beg) / CLOCK_PER_SEC
就能知道程序的運行時間了。
6.sizeof函數不只能夠初始化數組,還能夠顯示一個數組的大小:直接輸出sizeof(a)
就能夠看到數組\(a\)佔多少字節了。.p.s結構體也能夠用。
7.printf("%0*d", b, a)
表示輸出整數\(a\),若\(a\)的長度不足\(b\)時,高位用0補充。具體來講:
% 表示這是一個格式控制串 。
0 爲填充字符,表示當輸出長度不足指定長度時候,用 0填充不足的部分。
* 這個是指定輸出寬度。(在scanf中表示忽略這個整數)
d 這個表示輸出整數。
8.看到題目中出現二元組,能夠想象成二維平面上的點。數組