吶...
TOJ還是不給submit,
不過我感覺是沒問題了,就先放上來吧
這題主要算是math題吧
我到現在還是搞不太懂就是
這題基本上最直觀的解法就是直接加上去
結果還是TLE...
仔細看數字有到百億...
我看學長AC的時間是零
又想到費氏數列其實是有公式的
就開始往「是否能直接帶入公式」的方向思考
讓時間從O(n)變成O(1)
結果一直爬文阿
已知費氏數列的公式了,費氏數列合的公式怎麼求也不知道
浪費了兩三張計算紙感覺都在耍白癡,像是寫了好幾行得出了s(n-1)+f(n)=s(n)之類的廢話
後來觀察了一下,突然發現s(i)=f(i+2)-1,就莫名其妙發現的規律
用程式跑幾個大數字也正確就是了
像前5項的和(1+1+2+3+5)=第7項(13)-1=12
然後就想說很高興的帶公式直接O(1)得解
結果發現一個致命問題...
不知道怎麼取mod...
又試了一段時間,結果還是放棄了阿...公式解>口<
不知不覺打了一堆幹話:3
總之後來發現了,原來費氏數列還有一種求法是O(logn)
來源網站
參考了一下,就實作看看,原理甚麼的不懂
畢竟我根本沒學過矩陣
然後就做出來了...
時間的話跟直接加比起來,當n=100000000(億),
相加耗費2秒多,矩陣只要不到0.001秒
看來是沒問題了...
搞了一個晚上終於解決,只是原理不知道心就是有點癢癢的
比較一下費氏數列我已知的三個解法
1.加法 : O(n) ,易實作,足以應付大部分狀況
2.公式解 O(1) ,應該不會用到,而且不夠彈性,像這題就想不到方法取mod(可能是我太笨QQ)
3.矩陣 O(logn) ,數字特別大會TLE才需要用到(約超過10^8)
376.cpp(不能完全AC,但可以參考
更新(7/4
TOJ修好後發現一堆問題
可惡...果然沒那麼順利...
結果又爬了一堆文
硬生生地把矩陣的算法之類的搞懂
...
真的有夠麻煩...
反正...終於AC了...
376-2.cpp(AC正解版
2018年6月30日 星期六
TOJ169
TOJ掛掉好幾天了...
都不能更新好困擾...
如果附檔有錯就算了吧...
DP問題...
受夠了阿...
我這題當初大概想了一整天吧
後來看看其實也就這樣...
只是真的很難去想到就是...
也不然啦...只是實作很多沒注意到的地方出現bug...
我當時的思想:
1.暴力解的話,要得知第i根的狀況,最多必須掃過i-1根的值,然而->嚴重TLE
2.
仔細觀察,其實不必
舉 1 3 4 5 2 為例
當我們判斷到第4根(假設前面都判斷完了,並得到正確答案),
判斷和前面4的關係就好,
5大於前面的4,所以5的答案等於4的答案+1(多了4),也就是2(4的答案)+1=3
若判斷到2,2小於等於前面的5,所以答案為0
這樣是不是比暴力解快呢?
都不能更新好困擾...
如果附檔有錯就算了吧...
DP問題...
受夠了阿...
我這題當初大概想了一整天吧
後來看看其實也就這樣...
只是真的很難去想到就是...
也不然啦...只是實作很多沒注意到的地方出現bug...
我當時的思想:
1.暴力解的話,要得知第i根的狀況,最多必須掃過i-1根的值,然而->嚴重TLE
2.
仔細觀察,其實不必
舉 1 3 4 5 2 為例
當我們判斷到第4根(假設前面都判斷完了,並得到正確答案),
判斷和前面4的關係就好,
5大於前面的4,所以5的答案等於4的答案+1(多了4),也就是2(4的答案)+1=3
若判斷到2,2小於等於前面的5,所以答案為0
這樣是不是比暴力解快呢?
然而--->WA!!
我想也是,沒那麼輕鬆嘛...
甚至連範例都會錯就是
3.
以1 10 2 4 3 5 7為例
正解是0 1 0 1 0 3 4,然而用第2種思想卻得到0 1 0 1 0 1 2 ??
恩...仔細觀察相信馬上就會發現原因,
當我們要得到第i根的答案時
我們必須還要判斷擋住i-1根的那個棒棒是否也會擋住第i根,
如果會,那才可以直接第i根的答案=第i-1根的答案+1
如果不會被擋住,我們還要把前面的再吃掉才行
至於擋到第i根的棒棒找法也很好找,答案為0代表前一個擋到,答案為1代表前兩個擋到
拆成步驟的話(直接跳到第4根
1 10 2 4 3 5 7
5>3,吃掉3的答案,並判斷擋住3的那根會不會擋住5
1 10 2 4 3 5 7
5>4,沒被擋住,所以也要吃掉4的答案,也要判斷擋住4的那根
1 10 2 4 3 5 7
5<=10,被擋住了,因此不吃掉10的答案,也不用繼續判斷了
最後5的答案就是3的答案(0)+4的答案(1)+吃掉3和4(2)
也就是0+1+2=3
基本上就這樣,而已,知道實作方法,程式碼寫起來也不長
只是DP真的有夠煩惱
2018年6月24日 星期日
2018年6月23日 星期六
TOJ13
這個就完全的經典
DP中的背包問題之中的無限背包問題
演算法筆記也有
當初我應該也是隨隨便便似懂非懂地就抓下來AC了
我個人認為他比一般背包問題好懂啦...
我們開一個陣列,長度為體積+1(包含0),分別記錄當時體積能取得的最大價值
一開始當然預設為0囉
假設題目要的體積為10,三個物品的體積價值分別為
2,3 / 3,7 / 4, 1 / 1,1
我們就來實作吧
一開始的陣列狀況
0 0 0 0 0 0 0 0 0 0 0
代表0~10的最大價值都是0
接著我們把2,3放進去
當體積為0~1的時候,放不了(因為體積是2),所以最大價值維持原樣
體積為2~3的時候能放1個,最大價值為3
...4~5為6...10為15
最後變成
0 0 3 3 6 6 9 9 12 12 15
然而注意到了嗎,3,6,9,12,15怎麼來的?
是可以從少2個體積的值那個值+3得來
處理完了2,3的最大價值
接著我們把3,7丟進去
DP中的背包問題之中的無限背包問題
演算法筆記也有
當初我應該也是隨隨便便似懂非懂地就抓下來AC了
我個人認為他比一般背包問題好懂啦...
我們開一個陣列,長度為體積+1(包含0),分別記錄當時體積能取得的最大價值
一開始當然預設為0囉
假設題目要的體積為10,三個物品的體積價值分別為
2,3 / 3,7 / 4, 1 / 1,1
我們就來實作吧
一開始的陣列狀況
0 0 0 0 0 0 0 0 0 0 0
代表0~10的最大價值都是0
接著我們把2,3放進去
當體積為0~1的時候,放不了(因為體積是2),所以最大價值維持原樣
體積為2~3的時候能放1個,最大價值為3
...4~5為6...10為15
最後變成
0 0 3 3 6 6 9 9 12 12 15
然而注意到了嗎,3,6,9,12,15怎麼來的?
是可以從少2個體積的值那個值+3得來
處理完了2,3的最大價值
接著我們把3,7丟進去
當體積為0~2的時候,是放不下的,維持原樣
當體積為3時,我們有兩種選擇
1.維持原本陣列的值
2.更新陣列的值
原本的值是3,更新的值是0+7(體積0的最大值加上該物品價值)
我們要取最大值,因此被更新了
這樣持續下去更新體積4,5,6....10
會被更新成
0 0 3 7 7 10 14 14 17 21 21接著處理4,1
由於價值太小,會得到
0 0 3 7 7 10 14 14 17 21 21
處理1,1
在體積1的時候,更新的值(0+1)比原本的0大,更新
體積4的時候,也更新成5...
最後變成
0 1 3 7 8 10 14 15 17 21 22該陣列每個位置的值就代表那個體積可以存放的最大價值
體積0最多為0,體積1最多為1,體積2最多為3...
而假設題目要的是體積為10,也就是22
希望我打的這篇有人看得懂QQ
TOJ126
經典的DP問題,跟跳樓梯很像
奇怪的是
當初跳樓梯問題我明明會,
怎麼換成這個我就不會了...
還好有好心學長給我提示,非常感謝...
總之
假設有有2,3,5
那麼滿分是10,最低分是-10,對吧
我們可以開一個陣列,代表-10到10,共21格(包含0
我說過這題跟跳樓梯很像吧
跳樓梯從哪裡跳? 0階!
沒錯
一樣的我們就從0分開始跳
一開始都沒有任何紀錄時,就只有0分一種可能
所以0代表不可能,1代表有可能,則一開始是
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
再來呢,我們紀錄了第一筆資料 2分
我們答錯時,要扣2分,答對則要加2分
此時就是DP的關鍵,
拿出上一筆的資料 :
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0
奇怪的是
當初跳樓梯問題我明明會,
怎麼換成這個我就不會了...
還好有好心學長給我提示,非常感謝...
總之
假設有有2,3,5
那麼滿分是10,最低分是-10,對吧
我們可以開一個陣列,代表-10到10,共21格(包含0
我說過這題跟跳樓梯很像吧
跳樓梯從哪裡跳? 0階!
沒錯
一樣的我們就從0分開始跳
一開始都沒有任何紀錄時,就只有0分一種可能
所以0代表不可能,1代表有可能,則一開始是
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
再來呢,我們紀錄了第一筆資料 2分
我們答錯時,要扣2分,答對則要加2分
此時就是DP的關鍵,
拿出上一筆的資料 :
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
其中1是代表上一筆為止可能的分數吧,
那麼,可能的分數±2不就是這筆資料可能的分數,變成
0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0
同樣處理下一筆資料3,
再上一筆得到所有可能發生的分數±3
再處理資料5
最後就得到所有可能發生的分數
1 0 0 0 1 0 1 0 0 0 1 0 0 0 1 0 1 0 0 0 1
也就是-10,-6,-4,0,4,6,10
恩,這樣描述不知道能不能理解呢?
如果不能理解的話也是可以詢問的啦
TOJ315
這題看似基礎的快速冪
但他給的M實在太大了...
導致一點也不水阿...
個人目前想了一個晚上還是找不出正解
目前個人是覺得有三個以上的解
1.某個我想不出來的正解
2.把乘拆開用加的 ->太慢
3.用大數 ->太麻煩
大數直接複製14就好,
只是大數mod的部分要實作又要爬一堆資料了,實在不想浪費時間在這...
315-2.cpp(加法ver,時間很慢(370)
更新:
失敗想法:
f315.cpp(其實稍微調整一下c的取法,我認為有機會成功
更新:
315-3.cpp(大數ver,但時間還是很慢(360~400)
我想應該是mod方面的演算法需要改進
這方面我真的懶的研究...
更新:
315-2.1.cpp(加法ver,時間已經優化到極限了(60~80),
但他給的M實在太大了...
導致一點也不水阿...
個人目前想了一個晚上還是找不出正解
目前個人是覺得有三個以上的解
1.某個我想不出來的正解
2.把乘拆開用加的 ->太慢
3.用大數 ->太麻煩
大數直接複製14就好,
只是大數mod的部分要實作又要爬一堆資料了,實在不想浪費時間在這...
315-2.cpp(加法ver,時間很慢(370)
更新:
失敗想法:
f315.cpp(其實稍微調整一下c的取法,我認為有機會成功
更新:
315-3.cpp(大數ver,但時間還是很慢(360~400)
我想應該是mod方面的演算法需要改進
這方面我真的懶的研究...
更新:
315-2.1.cpp(加法ver,時間已經優化到極限了(60~80),
排行榜上0聽說好像是用大數做的,結果這題還是要用大數阿...
那可能就沒什麼我想像中的正解了
更新:
315-3.1.cpp(大數ver,不用寫麻煩的函數,輕輕鬆鬆直接用(0)
索性去問了學長
好心的他馬上丟了關鍵字給我「__int128」
哇!竟然還有這麼好用的東西我不知道
除了cin跟cout不能直接用還要定義以外
其他的加減乘除模都可以用
超棒的!!!
最後丟上去果然就runtime0了,好爽
更新:
315-3.1.cpp(大數ver,不用寫麻煩的函數,輕輕鬆鬆直接用(0)
索性去問了學長
好心的他馬上丟了關鍵字給我「__int128」
哇!竟然還有這麼好用的東西我不知道
除了cin跟cout不能直接用還要定義以外
其他的加減乘除模都可以用
超棒的!!!
最後丟上去果然就runtime0了,好爽
隨機img
F5會重置,然而不知有什麼用
可愛就夠了吧:3
網址是 : https://imgrandom.000webhostapp.com/imgrandom.gif
雖然是.gif檔,但是實際上是運作php的功能
可愛就夠了吧:3
網址是 : https://imgrandom.000webhostapp.com/imgrandom.gif
雖然是.gif檔,但是實際上是運作php的功能
2018年6月16日 星期六
TOJ238
簡單的BFS練習題...
明明是這樣的,可是不知道為甚麼我的runtime那麼久
好像BFS的題型我的Runtime都多別人幾倍...
又不知道怎麼開口要別人的code...
總之這題不難啦:3
應該也沒什麼陷阱
SET練習 (TOJ165
在學MST,發現竟然好難搞懂set的部分QQ
於是就來複習這題了
set算是基礎的資料結構
很多演算法其實都會用到就是了
沒有學好必定會吃虧
基本上set就是記住幾個函式寫法
Init(),find(),union(),same()
基本上就沒什麼麻煩了,也都很短就是
165.cpp
於是就來複習這題了
set算是基礎的資料結構
很多演算法其實都會用到就是了
沒有學好必定會吃虧
基本上set就是記住幾個函式寫法
Init(),find(),union(),same()
基本上就沒什麼麻煩了,也都很短就是
165.cpp
2018年6月15日 星期五
2018年6月14日 星期四
2018年6月13日 星期三
2018年6月12日 星期二
TOJ281
Tag很好心的給你math的提示,
查一下就能找到
關鍵字「皮克定理」
老實說這種東西我根本不想知道
其還有一題完整的(多邊形格子點),
但我懶得寫,感覺三角形就夠麻煩了
多邊形更麻煩的是你要判斷哪兩的點是相連的,
三角形則不用,每兩點必互相相連嘛~~
如果你有去查了,
你應該會得到一個公式 : i=A+1+b/2
i : 內部格子點含邊上的總數
A : 該多邊形面積
b : 該多邊形邊上的格子點數目
i當然就是我們要的,那A和b怎麼求呢...
恩...如果你聽過鞋帶公式,那可以直接將座標轉換成面積,
若沒有,也是可以用其他像海龍公式之類的,
反正都給你三個點的座標了,總有辦法的
接著就是比較麻煩的地方了...(其實也還好
計算邊上的格子點數
如果你寫過TOJ20了,那你可能會知道怎麼辦
如果沒有,那你則可以先寫TOJ20
另外依照我的AC程式結果
當三點連成一線的退化三角形,正解應該是線上格子點而非0
281.cpp(有點小疑惑但還是正解
查一下就能找到
關鍵字「皮克定理」
老實說這種東西我根本不想知道
其還有一題完整的(多邊形格子點),
但我懶得寫,感覺三角形就夠麻煩了
多邊形更麻煩的是你要判斷哪兩的點是相連的,
三角形則不用,每兩點必互相相連嘛~~
如果你有去查了,
你應該會得到一個公式 : i=A+1+b/2
i : 內部格子點含邊上的總數
A : 該多邊形面積
b : 該多邊形邊上的格子點數目
i當然就是我們要的,那A和b怎麼求呢...
恩...如果你聽過鞋帶公式,那可以直接將座標轉換成面積,
若沒有,也是可以用其他像海龍公式之類的,
反正都給你三個點的座標了,總有辦法的
接著就是比較麻煩的地方了...(其實也還好
計算邊上的格子點數
如果你寫過TOJ20了,那你可能會知道怎麼辦
如果沒有,那你則可以先寫TOJ20
另外依照我的AC程式結果
當三點連成一線的退化三角形,正解應該是線上格子點而非0
281.cpp(有點小疑惑但還是正解
TOJ185
說實在我也不確定是不是這樣解
不過我看測資這樣,就猜是這樣了
也沒有試著證明過
總之
兩個序列乘積總和的最大值,
一定是最大*最大+第二*第二....
這個要證明的話可能要去問數學老師了
這題要實作不難,
果然最難的還是證明的部分,
或許哪天我有空去問數學老師後再更新這篇吧...
...
...
...
隔天更新
...
後來想了一下
假設只有各只有兩個數,a,b x,y
a>b x>y
可以變成a-b>0 ,x-y>0
則兩式相乘為(a-b)(x-y)>0 (兩個正整數相乘必>0)
變成ax-ay-bx+by>0
也就是ax+by>ay+bx
這就證明完了
至於多個數呢
其實也只是以上的延伸
我就懶得再更新了
185.cpp
不過我看測資這樣,就猜是這樣了
也沒有試著證明過
總之
兩個序列乘積總和的最大值,
一定是最大*最大+第二*第二....
這個要證明的話可能要去問數學老師了
這題要實作不難,
果然最難的還是證明的部分,
或許哪天我有空去問數學老師後再更新這篇吧...
...
...
...
隔天更新
...
後來想了一下
假設只有各只有兩個數,a,b x,y
a>b x>y
可以變成a-b>0 ,x-y>0
則兩式相乘為(a-b)(x-y)>0 (兩個正整數相乘必>0)
變成ax-ay-bx+by>0
也就是ax+by>ay+bx
這就證明完了
至於多個數呢
其實也只是以上的延伸
我就懶得再更新了
185.cpp
2018年6月11日 星期一
TOJ20
就數學題
曾經聽學長說好像要學什麼向量之類的才能解
反正我是想一想就覺得應該是這樣就過了
剛剛查了一下好像是二上的數學
比較要注意的地方就兩點y軸和x軸相同的狀況,
我因為這樣吃了幾次RE,
基本上這題也是蠻水的
2018年6月10日 星期日
2018年6月9日 星期六
TOJ36
本題重點
將A*A*A*A*A*...11個
=(A^11)=(A^5)^2*A=(((A*A)^2)*A)^2*A
這樣比起相乘10次,
大幅縮短了很多時間,可避免TLE
這就是快速冪
另外(A*A)%B跟(A%B)*(A%B)是一樣的,用後者避免溢位出現WA
將A*A*A*A*A*...11個
=(A^11)=(A^5)^2*A=(((A*A)^2)*A)^2*A
這樣比起相乘10次,
大幅縮短了很多時間,可避免TLE
這就是快速冪
另外(A*A)%B跟(A%B)*(A%B)是一樣的,用後者避免溢位出現WA
TOJ325
這個嘛...
有點類似126的DP問題
題目化簡就是找到可以組成<=總數一半的最大組合
實作的話
假如題目是3,4,1,2,總和為10
開個大小為10+1的bool判斷(其實這題只要6就夠了)
一開始預設0為true;
1 0 0 0 0 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0 0,已知0可以,則0+3可以
1 0 0 1 1 0 0 1 0 0 0,已知0,3可以,則0+4,3+4可以
1 1 0 1 1 1 0 1 1 0 0,已知0,3,4,7可以,則0,1,3,4,5,7,8可以
1 1 1 1 1 1 1 1 1 1 1,懶得打了...
總之就是這樣,
有不懂的話不如就研究程式碼吧
325.cpp
有點類似126的DP問題
題目化簡就是找到可以組成<=總數一半的最大組合
實作的話
假如題目是3,4,1,2,總和為10
開個大小為10+1的bool判斷(其實這題只要6就夠了)
一開始預設0為true;
1 0 0 0 0 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0 0,已知0可以,則0+3可以
1 0 0 1 1 0 0 1 0 0 0,已知0,3可以,則0+4,3+4可以
1 1 0 1 1 1 0 1 1 0 0,已知0,3,4,7可以,則0,1,3,4,5,7,8可以
1 1 1 1 1 1 1 1 1 1 1,懶得打了...
總之就是這樣,
有不懂的話不如就研究程式碼吧
325.cpp
TOJ14
其實就是基本的大數運算(實際上也只有相乘
我也是第一次碰大數...
一般的方法好像都是用int陣列,每個陣列儲存每個位數
像演算法筆記就是
結果TLE
接著就是找找看其他大數演算法
找到了Karatsuba大數乘法演算法
實作後也不知道為什麼更慢更慢更慢
後來我想想,更本沒必要只儲存一個位數啊幹,浪費位置
所以我就把每個陣列儲存的位數改成9位數(不能再多了)
結果就是一些亂七八糟的溢位問題
耗了我兩三天的假日:<
總算還是AC這題了
不過Rank還有更快的
據說是用快速傅立葉轉換做的
這個我就不清楚了,也不想了解,看到名子就豆頁疒甬
反正,能過就好了,對吧?
訂閱:
文章 (Atom)