麦森数(洛谷P1045题题解,Java语言描述)
題目要求
題目鏈接
分析
這題挺經典的,快速冪取模算法,如果求出大數(shù)再取模就可能T掉。
之前有篇文章寫了這個算法:《快速冪算法詳解&&快速冪取模算法詳解》
既然是Java,那就要使用出Java的特點!BigInteger還在呢,都不必手寫快速冪。
記住,哪怕是使用快速冪的pow再mod也會炸,所以使用modPow(),直接把模求出來。
你可能會懷疑,(2P?1)mod(10500)(2^{P}-1)mod(10^{500})(2P?1)mod(10500)?
是的,這個式子可以化為:(2P)mod(2500)?1(2^{P})mod(2^{500})-1(2P)mod(2500)?1,寫成代碼就是:TWO.modPow(p, 10.pow(500)).substract(1)。
注意上面的數(shù)字是代指,其實基本全是BigInteger對象。
你覺得恍然大悟?
其實不對,做個比方:2…00000000,中間有1000個0,末尾500位全是0,那怎么辦,得到的不是0嗎?0-1就是-1??取模得了-1?
對吧,思考要深入!
所以我們的代碼錯了嗎?
也不是,首先要清楚的是,假設先取冪再取模,底數(shù)一定是2的冪次。
我們看一看2的冪次:2、4、8、16、32、64、128、256、512、1024、2048…
規(guī)律就是,末尾一定是2、4、8、6在循環(huán),所以不可能是0啊!
那我們這么做就是對的!
好,解決了求冪取模的問題,接下來是,你直接用了快速冪取模,沒求冪次,怎么得到2P?12^P-12P?1的位數(shù)?
首先我們知道2P?12^P-12P?1與2P2^P2P有著相同的位數(shù)(因為2的冪次末位不為零,所以2P2^P2P減去1,位數(shù)并不會改變),所以我們可以直接求2P2^P2P的位數(shù)。
我們不妨設2P=k2^P=k2P=k,10n10^n10n位數(shù)為(n+1)(n+1)(n+1),只需換底為10,冪次+1即為所求。
2=10lg22=10^{lg2}2=10lg2 => 2P=(10lg2)P=10p?lg2=k2^P=(10^{lg2})^P=10^{p*lg2}=k2P=(10lg2)P=10p?lg2=k
所以位數(shù)就是p?lg2+1p*lg2+1p?lg2+1,代碼表示就是(int)(Math.log10(2)*p)+1
接下來講代碼編寫的注意事項,稍有不注意就會爆炸:
- BufferedReader一定要用,否則必炸四個點好像是
- 不要用String去操作,用BigInteger很穩(wěn)
- 不要直接取模,用快速冪取模
- 所有的補位和拼接全用StringBuilder
- 不要分次輸出,盡量一次輸出
- 連接\n的時候用單引號比較好
- 洛谷識別ONE但不識別TWO,所以必須換成new BinInteger(“2”)
- 求BigInteger對象的位數(shù)不能用bitLength(),那是二進制位數(shù);可以使用toString()后的length()來求
- ……
有一說一,這題用Java寫,操作性蠻強的。
測試數(shù)據(jù)1:
in
756839
out
227832
18288448825429774219846956862417770870640302475247
92828312585598040121588421297674731878093115313182
16753914541797571068392534875840214937021204750378
89055619401647443568291937923950889819022384242323
28767636683196318572845992994357198238764218257600
09234774987448978769799124034384499030364505405943
84275497234460834579807796823701486980464630401353
54915833132974601389482848422119619724789014565809
44396409267168409183491136926492417685905113427201
26927068487680404055813342880902603793328544677887
測試數(shù)據(jù)7:
in
607
out
183
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000531137992816767098689588206552468
62732959311772703192319944413820040355986085224273
91625022652292856688893294862465010153465793376527
07239409519978766587351943831270835393219031728127
AC代碼(Java語言描述)
import static java.math.BigInteger.*;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigInteger;public class Main {public static void main(String[] args) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));String p = reader.readLine();BigInteger num = new BigInteger("2").modPow(new BigInteger(p), new BigInteger("10").pow(500)).subtract(ONE);reader.close();int length = num.toString().length();StringBuilder result = new StringBuilder();if (length < 500) {for (int i = 0; i < 500-length; i++) {result.append('0');}result.append(num);} else {result.append(num);}String str = result.toString();result = new StringBuilder();result.append((int)(Math.log10(2)*Integer.parseInt(p))+1).append('\n');for (int i = 0; i < 10; i++) {result.append(str, i*50, i*50+50).append('\n');}System.out.println(result);} }總結
以上是生活随笔為你收集整理的麦森数(洛谷P1045题题解,Java语言描述)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java】Java反射机制重点总结
- 下一篇: 质数筛(洛谷P5736题题解,Java语