如果n為偶數,則將它除以2,
如果n為奇數,則將它加1或者減1。
問對於乙個給定的n,怎樣才能用最少的步驟將它變到1。
其實這個問題就是如何將整數變數乘上整數常數問題轉化為最少的移位運算和加法運算問題. 假設乙個計算機只提供加減法和移位一位的指令,那麼這個問題就相當於如何用最少的加減法和移位指令來計算乘上乙個整數常數的演算法.
這個演算法很簡單:
int cnt(int x)
也就是說,在x是偶數時採用除2。x是奇數(x>=5),
如果除4餘1採用減1,如果除4餘3採用加1。
i)需要證明,對於x=2k,採用加1或減1的方案都沒有除2好。
i1) 2k=>k比2k=>2k+1好,
2k+1下一步不能再到2k+1-1=2k(走回頭路了),所以這個方案比如是兩次後變成
2k=>2k+1=>...=>2k+2s=>k+s (2s+1步s>=1)
而 2k=>k的方案到k+s只需要2k=>k=>k+1=>...=>k+s (s+1步)
所以2k=>k的方案必然好於2k=>2k+1的方案。
i2)2k=>k比2k=>2k-1好
同樣,對於2k=>2k-1的方案,必然如下變換:
2k=>2k-1=>....=>2k-2s=>k-s (2s+1步變換)
而2k=>k的方案可以通過s+1步達到同樣目的
2k=>k=>k-1=>...=>k-s (s+1步)
所以2k=>k的方案必然好於2k=>2k-1方案。
由此,我們得到第乙個結論:對於偶數,必然採用除2的方案。
ii)我們來證明對於x=4k+1的情況,採用x-1的方案不差於採用x+1的方案。
由結論1,採用x+1的方案必然是
4k+1=>4k+2=>2k+1
然後必然是
4k+1=>4k+2=>2k+1=>2k+2=>k+1或
4k+1=>4k+2=>2k+1=>2k=>k
所以採用這個方案必然是通過4步到達k+1或k
但是通過x=>x-1方案我們可以
4k+1=>4k=>2k=>k
4k+1=>4k=>2k=>k=>k+1
分別通過3步或4步到達k或k+1,所以我們知道,對於x=4k+1,x=>x-1的方案不差於x=>x+1的方案。所以為了達到最優結果我們總可以採用x=>x-1方案。
iii)最後一步證明對於x=4k+3,x=>x+1方案不差於x=>x-1方案。
對於x=>x-1方案,根據結論1,其變換必然是
4k+3=>4k+2=>2k+1,所以下面兩步變換必然導致
4k+3=>4k+2=>2k+1=>2k+2=>k+1 或
4k+3=>4k+2=>2k+1=>2k=>k
所以同樣是經過4步變換得到k或k+1
而採用x=>x+1的方案,我們總可以使用
4k+3=>4k+4=>2k+2=>k+1
4k+3=>4k+4=>2k+2=>k+1=>k
經過3步或4步到達k+1或k,所以對於x=4k+3,採用x=>x+1方案不差於x=>x-1方案。
由上面結論我們可以知道,使用前面的演算法必然能夠找到最優結果。
時間複雜度是o(log(n)),空間複雜度是o(log(n))(因為採用了遞迴),實際上,這個遞規是尾遞規,通過簡單的優化,可以到達時間複雜度位o(log(n))但是空間複雜度為o(1)的結果。
當然對於實際上的cpu,移位指令都可以移動任何數目的位元位,這時,就沒有上面簡潔的演算法了,一般來說,我們將需要使用動態規劃來計算最優方案
矩陣乘法的常數優化
矩陣乘法的常數優化 philipsweng 雖然說作為鍵盤科學家,我們更應該關心程式的時間複雜度。但是乙個寫的不好的程式可能在實際執行會跟時間複雜度更差的程式差不了多少。我們我們也應該注意程式的常數優化。對於矩陣乘法來講。我們實際上可以比較這兩種打法。實際上第二種打法在絕大多數情況下效率約為第一種的...
大整數乘法問題
大整數乘法問題 應用陣列解決,由於計算機的精度是有限的,因此單純使用程式語言提供的原子資料型別來 完成兩個大整數的乘法顯然是不切實際的。可以考慮用兩個陣列來分別儲存一些大於10的整數,這些數字按順序 排列在一起,分別表示乙個大整數的每一位上的數字,於是大整數的儲存問題就解決了。然後按照基本乘法規則 ...
OI中C 常數問題及其優化
常數是個謎,卡常是件很煩的事,被常數坑死的oier已經不少了 常數不可避免,但是可以理性地去優化 當時間複雜度已經難以優化時,考慮常數優化 i o讀入和輸出 如果量小倒也沒什麼,如果大規模讀入或者輸出,c 自帶的方式是很慢的 首先,拒絕cin cout,實在是太慢了,受不了 接著scanf prin...