欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

麦森数(洛谷P1045题题解,Java语言描述)

发布时间:2025/3/15 30 豆豆
生活随笔 收集整理的这篇文章主要介绍了 麦森数(洛谷P1045题题解,Java语言描述) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

题目要求

题目链接

分析

这题挺经典的,快速幂取模算法,如果求出大数再取模就可能T掉。

之前有篇文章写了这个算法:《快速幂算法详解&&快速幂取模算法详解》

既然是Java,那就要使用出Java的特点!BigInteger还在呢,都不必手写快速幂。
记住,哪怕是使用快速幂的pow再mod也会炸,所以使用modPow(),直接把模求出来。

你可能会怀疑,(2P−1)mod(10500)(2^{P}-1)mod(10^{500})(2P1)mod(10500)
是的,这个式子可以化为:(2P)mod(2500)−1(2^{P})mod(2^{500})-1(2P)mod(2500)1,写成代码就是:TWO.modPow(p, 10.pow(500)).substract(1)。
注意上面的数字是代指,其实基本全是BigInteger对象。

你觉得恍然大悟?
其实不对,做个比方:2…00000000,中间有1000个0,末尾500位全是0,那怎么办,得到的不是0吗?0-1就是-1??取模得了-1?
对吧,思考要深入!
所以我们的代码错了吗?

也不是,首先要清楚的是,假设先取幂再取模,底数一定是2的幂次。
我们看一看2的幂次:2、4、8、16、32、64、128、256、512、1024、2048…
规律就是,末尾一定是2、4、8、6在循环,所以不可能是0啊!
那我们这么做就是对的!

好,解决了求幂取模的问题,接下来是,你直接用了快速幂取模,没求幂次,怎么得到2P−12^P-12P1的位数?
首先我们知道2P−12^P-12P12P2^P2P有着相同的位数(因为2的幂次末位不为零,所以2P2^P2P减去1,位数并不会改变),所以我们可以直接求2P2^P2P的位数。
我们不妨设2P=k2^P=k2P=k10n10^n10n位数为(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=10plg2=k
所以位数就是p∗lg2+1p*lg2+1plg2+1,代码表示就是(int)(Math.log10(2)*p)+1

接下来讲代码编写的注意事项,稍有不注意就会爆炸:

  • BufferedReader一定要用,否则必炸四个点好像是
  • 不要用String去操作,用BigInteger很稳
  • 不要直接取模,用快速幂取模
  • 所有的补位和拼接全用StringBuilder
  • 不要分次输出,尽量一次输出
  • 连接\n的时候用单引号比较好
  • 洛谷识别ONE但不识别TWO,所以必须换成new BinInteger(“2”)
  • 求BigInteger对象的位数不能用bitLength(),那是二进制位数;可以使用toString()后的length()来求
  • ……

有一说一,这题用Java写,操作性蛮强的。

测试数据1:
in
756839
out
227832
18288448825429774219846956862417770870640302475247
92828312585598040121588421297674731878093115313182
16753914541797571068392534875840214937021204750378
89055619401647443568291937923950889819022384242323
28767636683196318572845992994357198238764218257600
09234774987448978769799124034384499030364505405943
84275497234460834579807796823701486980464630401353
54915833132974601389482848422119619724789014565809
44396409267168409183491136926492417685905113427201
26927068487680404055813342880902603793328544677887

测试数据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语言描述)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。