國慶七天樂——第一天
20171001
所學內容:分治倍增,搜索模擬,位運算+考試
【時間復雜度】
表示運行時間的增長趨勢
T(N)=T(N/2)+O(1) 二分查找
T(N)=2*T(N/2)+O(1) 線段樹的節點個數
T(N)=2*T(N/2)+O(N) 快排/歸並排序
T(N)=a*T(N/b)+f(1) è主定理
【位運算】
含義 |
Pascal語言 |
C語言 |
Java |
按位與 |
a and b |
a & b |
a & b |
按位或 |
a or b |
a | b |
a | b |
按位異或 |
a xor b |
a ^ b |
a ^ b |
按位取反 |
not a |
~a |
~a |
左移 |
a shl b |
a << b |
a << b |
帶符號右移 |
a shr b |
a >> b |
a >> b |
無符號右移 |
a>>> b |
X&(1<<k) 取k的第k位
(x>>k)&1 第k位是1還是0
Lowbit(x)=x&(-x)
X=x-x&(1<<k) 清除第k位
【遞歸算法】
1階乘:f(0)=1
f(i)=f(i-1)*i
2.漢諾塔 h(1)=1;
H(n)=h(n-1)*2+1;
H(n)=2^n-1à方案總數
Void solve(int n,char a,charb,char c)
{
If(n>1) solve(n-1,a,b,c)
Printf(“%c%c\n”,a,b);
If(n>1)solve(n-1,c,b,a)
}
3.不開數組,實現一個字符串的倒序輸出
Void haha()
{
Char ch;
If(~scanf(“%c”,&ch); //按位取反,判斷是否為-1(11111111)
Haha();
Printf(“%d”,ch)
}
爆棧 :10000層之內
【模擬】
1 統計2出現了幾次
I%10,i/=10;
2.接水問題
每次維護最早接完水的人(堆)
誰先接完,就讓下一個人到他那裏去
3.字符串展開
記錄每一個“-”,記錄最後變成了什麽字符串
【搜索:dfs/bfs】
搜索加速
剪枝:減掉所有不可能出解的廢狀態
加速:首先走更有可能有解的狀態
叠代加深搜索 :用於不知道最優解大小的
一層一層的搜(bdfs)
雙端搜索:用於狀態數增長過於迅速
起點和終點一塊搜
優化狀態存儲方式:加速狀態的拷貝
位運算
- 老鼠走迷宮
走到終點輸出,否則枚舉四個方向,不越界&&沒走過&&沒有墻,搜索。
- 八皇後
搜索剪枝,二進制加速(有位運算版的)
- 八數碼
Bfs
******** 康托展開:
把排列看成一個數,第i位為N-i+1進制
如果第i位為是ai,且之前有bi個數比他小,那麽他在該進制下的值是ai-bi-1
- 帶鑰匙的迷宮問題;
有鑰匙和沒有鑰匙是兩個圖
遇到門:如有我之前已經拿到鑰匙了,那這扇門就不存在了,否則這扇門就是一堵墻
- mayan遊戲
如果顏色不足三個,剪掉
所有的左右交換可視為左邊的右移
合理使用算法判斷十字形
相同顏色的點用交換
- 鬥地主
從大到小搜;先出炸彈,順子,,盡可能的多出牌,直到最後,三帶一,三帶二,對子,單張等,可以從最後的狀態裏掃出來O(N),無需搜索
- 滑雪
Dpi,j表示從(I,j)位置向下滑最遠距離,通過搜索轉移
************************tips**************************
1對拍,能寫對拍的難度都相對較小
2.主要優化措施在寫題之前就要想好,這決定了狀態的存儲格式
3.不要寄希望於優化常數,一定是有明顯剪枝沒有考慮清楚
4.有良心的出題人一般會把時限開到他能寫出的最快程序的時間的兩倍
********************調試**************************
- 最好是gdb+vim
- 搜索過程輸出
- 使用錯誤流,assert等
#include<cassert>
assert(level<=n);
- 存狀態用struct可能會更容易調試
【分治】
- 猜數遊戲 logn
- 跳石頭à二分
設x為最小距離最大值,(1-所有數的最大值)
如果某兩塊石頭之間的距離小於x,移走一塊石頭
如果最後移走的石頭總數>m,說明x過小,l=x;
反之 r=x;
- Can you find it
計算出x- ci,並把Ai+Bi的所有可能性的值離線算出來Dz,二分查找這個數.
*************騷操作*******************************
Lower_bound() 第一個大於等於的位置,否則返回end();
Upper_bound() 第一個大於的位置,否則返回end()
- 借教室
二分訂單總數,求出教師數量的前綴和,當天剩余教室的數量,判斷當天的數量是個滿足(<0不滿足)
一種奇怪的二分:二分比例為 0.618:1
根據大量科學研究得出,斐波那契數列數的位置越靠後,前一個數和後一個數的比值就更接近黃金比(這是科普)
- 函數極值:三分
講數據分成三分,(1,2,3)
如果1+2<2+3,就舍去1(或3)
- Rode:三分套三分
寫一個cala()函數來計算時間
三分固定起點後三分固定終點,比較得出最短時間
終點(起點(cala()))
7.歸並和快排
8. 逆序對:樹狀數組/在歸並排序是計算交換的次數(計數器)
【倍增】
- 快速冪
- 快速乘(把快速冪中的乘號變成加號,而且不能mod)
- Lac (jump[t][x]=jump[t-1][jump[t-1][x]]精華!)
先把兩個節點的深度利用jump數組調成一樣的(跳2的冪次)
然後兩個節點一塊跳(從大到小算:2^10à2^9à2^8à…-à2^0.)
用位運算來弄。
如果兩個節點跳到一起了,就返回,否則就繼續往上跳
最後可以保證,當前他們的父節點就是他們的最近公共祖先
【普通分塊】
設分塊的長度為s,數組的總長度為n
分塊的大小=min(s,n/s),≈sqrt(n)
【大點小點分塊】
對於大於sqrt(n)à分塊
小於sqrt(n)à普通暴力
**********************task****************************
T1:數論
=2^(n-1);
因為 c(0,n)+c(1,n)+c(2,n)+…..+c(n-1,n)+c(n,n)=2^n;
所以如果只取一半的話,那就是2^n/2=2^(n-1)
T2:模擬
把X,y數組排序,利用相似的性質,表示現線段的長度,再作比較
T3:數據結構
Trie樹+合並相同後繼節點
國慶七天樂——第一天