看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《luke90512 (阿神)》之銘言: : input為一系列的整數,範圍是1~2*10^100 : 對每個input假設為n : 計算s=1^1+2^2+3^3+...+n^n : 只取s的個位數作為答案 : 程式碼(Code):(請善用置底文網頁, 記得排版) : http://ideone.com/BQz0Uz 其他恕刪,我看你後來改的 code 還是有用到 pow 函式 (恕我沒細看理解), 然後早上起床想了一下,做了一點推導可以參考一下。 數學表達不好,見諒,另我也不保證這想法是可 AC 的。 --- 首先在意的是 1^1, 11^11, 21^21 尾數是多少; 再來在意的是 2^2, 12^12, 22^22 尾數是多少; 然後發現其實有規律可詢, 像 2^2 尾數是 4 ; 12^12 尾數是 6; 22^22 尾數是 4 ;32^32 尾數是 6... ; 依此類推,經過一點推導後結論如下 (可能有推錯,不過目前驗證是對的) --- n/10=even, n=10=odd, n/10=even ----------------------------- 0 : 尾數必為 0 (0^0= 0, 10^10=..0, 20^20=..0) 1 : 尾數必為 1 (1^1= 1, 11^11=..1, 21^21=..1) 2 : 尾數變化 4 -> 6 -> 4 -> 6 -> ... (2^2= 4, 12^12=..6, 22^22=..4) 3 : 尾數變數 7 -> 3 -> 7 -> 3 -> ... (3^3=..7, 13^13=..3, 23^23=..7) 4 : 尾數必為 6 (4^4=..6, 14^14=..6, 24^24=..6) 5 : 尾數必為 5 (5^5= 5, 15^15=..5, 25^25=..5) 6 : 尾數必為 6 (6^6= 6, 16^16=..6, 26^26=..6) 7 : 尾數變化 3 -> 7 -> 3 -> 7 -> .... (7^7=..3, 17^17=..7, 27^27=..3) 8 : 尾數變化 6 -> 4 -> 6 -> 4 -> .... (8^8=..6, 18^18=..4, 28^28=..6) 9 : 尾數必為 9 (9^9=..9, 19^19=..9, 29^29=..9) --- 上面如果會看的話,可以做很多事了,拿簡單的例子來講, 如果是算 1^1 + .... + 10^10 ,取變化的第一個數字 (像2的話就是 4,3的話是 7) 1^1 + .... + 10^10 = 1 + 4 + 7 + 6 + 5 + 6 + 3 + 6 + 9 + 0= 47,尾數=7 然後注意到,其實 10^10 有沒有加是無所謂、不影響結果的。 如果是算 11^11 + .... + 20^20 ,取變化的第二個數字 ( 2的話取 6,3的話取 3) 11^11 + .... + 20^20 = 1 + 6 + 3 + 6 + 5 + 6 + 7 + 4 + 9 + 0 = 47,尾數=7 再推廣下去的話,會變成, 1+.....+10^10 -> 47 ---> 尾數 7 1+.....+20^20 = (1+....+10^10) + (11^11 +....+20^20) -> (7 + 7) = 14 -> 尾數 4 1+.....+30^30 -> 7+7+7 = 21 --> 1 1+.....+40^40 -> 7*4 = 28 --> 8 1+.....+50^50 -> 7*5 = 35 --> 5 換句話說,如果 n 是 10 的倍數,或是10的倍數減 1, 那尾數就變成了.. ( (n+1) / 10 ) * 7 % 10 然後接下來的剩下不是 n 的部份怎麼做呢?回到最上面一開始給你的規則, 去建表相加。 ------------ 再來是,上面的 1+....+10^10 , 1+....+20^20,是以 10 為 gap ,但其實有更好的 規則,是 gap 一次考慮 20 個,你會發現如下 1+....+20^20 ---> 尾數 = 4 1+....+40^40 ---> 尾數 = 8 1+....+80^80 ---> 尾數 = 2 1+....+100^100 ---> 尾數 = 0 1+....+120^120 ---> 尾數 = 4 ----> 這裡開始循環 8 2 0 ... 上面這些可以建表。 有些超過題目太多就不說了,假設題目是給你 1+...+88^88 的話... (1) 1+...+80^80 --> 尾數 = 2 < 從 n gap 20 規則取得, O(1) > (2) 81^81 + ....+ 88^88 ,從最一開始給你的規則判斷, ---> 1 + 4 + 7 + 6 + 5 + 6 + 3 + 6 = 38 --> 尾數 = 8 最後得到 2+8 = 10,10%10 = 0, 這就是結果了。 在第二步要加快速度的話我會建立一個表,大概長這樣 int times_20[] = {0,1,4,7,6,5,6,3,6,9, // 00~09, 20~29, 40~49 尾數 0,1,6,3,6,5,6,7,4,9}; // 10~19, 30~39, 50~59 尾數 int column_times[20]; column_times[0] = times_20[0]; for(i=1; i<20; ++i) column_times[i] = column_times[i-1] + times_20[i]; 上面的 column_times 事先算好,然後第二步就可以就可用 column_times 去做,O(1), 於是整體的效能反而落在,大數(n) 除以 整數(20) / 大數(n) Mod 整數 (20), 上面的 除以20 和 Mod20,是同一個副函式可做出來的東西。 --- 這可能不是最快的, implement 沒太大興趣,希望有給您一點靈感。 -- ~ 這輩子與神手無緣 我只好當神獸了 ~ 卡卡獸 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 180.177.76.161
hichcock:讚...程式只是工具, 重點是你怎麼解問題 01/22 09:35
EdisonX:想了一下,最後的 /20 , %20 還有機會偷工,不過我懶了 XD 01/22 09:56
stimim:也可以先算 1^1+...+n^n % 5 還有 1^1+...+n^n%2 再用 CRT 01/22 10:52
stimim:(i^i)%2 是兩個一循環,(i^i)%5 是 20 個一循環 01/22 10:56
EdisonX:s 大方法漂亮, 不過「算落在哪個循環」似乎還是要大數除 ? 01/22 11:08
suhorng:20個一循環 所以100個也會循環 吧? 01/22 11:36
suhorng:(i^i)%5 可以從 (i^(i%4))%5 來看 大概是 20 的由來? 01/22 11:37
stimim:n%20 應該不能算是大數除吧 XD ,只要看最後兩位就好了 01/22 11:42
EdisonX:熊熊腦鈍, 確實拿最後兩位數, 配合 CRT 就出來了, 謝謝 :) 01/22 11:57
luke90512:感謝Ed大還有各位~ 看來頭腦要再靈活一點了! 01/22 12:29
ericinttu:推一下, 我還沒想到底. 01/22 13:52
damody:推e大 推人超好~ 01/22 13:54
luke90512:請問一下CRT是什麼呢? 01/22 15:53
suhorng:chinese remainder theorem 01/22 16:03
stimim:中國剩餘定理 01/22 16:03
Donze:((n-1)/10)*7%10 那邊應該是n+1 因為19^19跟20^20的結果一樣 01/22 17:41
Donze:然後一次考慮20個那邊第一行應該是 1+....+20^20才對 01/22 17:42
謝謝 D 大指正 :) ※ 編輯: EdisonX 來自: 180.177.76.161 (01/22 17:57)
FrankWOO:sum(i^i)的個位數每180個一循環,所以只要算(i^i)%180 01/22 18:09
Donze:有人可以解釋一下推文的循環都怎麼出來的嗎? 01/22 18:40
EdisonX:(i^i)%180,這個要配大數的話大概沒辦法吧? 10^n/180 不會 01/22 18:59
EdisonX:是整數吧 01/22 19:01
stimim:費馬小定理 x^(p-1)%p=1 若p是質數,所以i^i%5=i^(i%4)%5 01/22 19:04
stimim:所以最多 5*4 個就會循環 01/22 19:05
stimim:而 (1^1+...+n^n)%5 最多只要再 5 倍,也就是 100 個一循環 01/22 19:05
EdisonX:< 小聲的說,數學不好其實可以先寫一份簡易大數,用暴力觀查 01/22 19:05
EdisonX: 多暴力呢? 就和 分數化循環小數 不用數學解 一樣暴力 > 01/22 19:06