这道题可以分为两个模块,第一个模块为求的位数,第二个模块为求的后500位(不足补零)。我们主要来解决第一个模块:
一、求位数
首先我们知道 与 有着相同的位数,因为2的次方满足了最后一位不为零的要求,所以减一后位数并不会改变,那么我们可以直接求 的位数。那么怎么求位数呢?我们不妨设 ,根据 的位数为 ,我们只要想办法把 中的底数2改为10,指数加一就是位数了。由此想到用10的几次方来代替2,那么就不难想到 ,这样便可以把 中的2代换掉,变为 。根据乘方的原理,将p乘进去,原式便可化为我们最终想要的形式 了,所以位数就是 。(提醒一下,C++中cmath库自带log10()函数…)
二、求最后500位数
这个绝对难不倒大家,裸的高精快速幂,经过NOIP2017初赛的RP++后,相信很多人都已经会了快速幂了,所以我在这里不再赘述,只是提供一种相对较为简便的高精乘法(见程序)
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
long long str[100000];
int main()
{
int n,len=1;
cin >> n;
int s = n * log10(2) + 1;
str[0] = 1;
cout << s << endl;
while (n != 0) {
int z = 0, k;
if (n >= 27)
{
k = 27;
n -= 27;
}
else
{
k = n;
n = 0;
}
long long f = pow(2, k);
for (int j = 0; j <= len; ++j)
{
long long temp = f * str[j] + z;
z = temp / 10;
str[j] = temp % 10;
if (j == len - 1 && z != 0&&len<500)++len;
}
}
if (str[0] != 0) str[0] -= 1;
else
{
str[0] = 9;
str[1] -=1;
}
if (str[1] == '-1')
{
str[2] -= 1;
str[1] = 9;
}
for (int i = 499, j = 0; i >= 0; --i, ++j)
{
cout << str[i];
if (j == 49)
{
cout << endl;
j = -1;
}
}
return 0;
}