TAT,一开始读错题了,以为输出的位数是超过500就默认输出500的。还奇怪为什么评论区里大家都在说什么位数计算公式,对数计算的换底公式啥的。
原来输出的是原数的位数!
对于一个数k,它的位数是lg(k)+1。然而对于这道题得到一个可以放到cmath函数中的k是很困难的,题目要求的输出也只是500位。但是题目给我们的是k = 2^n - 1中的n,那么就可以用换底公式计算了,lg(k) = log2(k)/log2(10) = n/log2(10)。虽然减去一个1,不过对log的计算是没有任何影响的。
之后写个高精乘,用快速幂计算就好了,超过500位的部分忽略即可。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define P 100000
using namespace std;
int n;
struct BigInt{
long long h, a[200];
BigInt(){
h = 0;
memset(a, 0, sizeof a);
}
void print(){
for(int i = 100; i; i--){
if(i%10 == 0 && i != 100) putchar('\n');
printf("%.5lld", a[i]);
}
}
BigInt operator * (BigInt k) const{
BigInt res;
res.h = k.h+h+2;
for(int i = 1; i <= h; i++)
for(int j = 1; j <= k.h; j++){
res.a[i+j-1] += a[i] * k.a[j];
res.a[i+j] += res.a[i+j-1] / P;
res.a[i+j-1] %= P;
}
while(!res.a[res.h]) res.h--;
res.h = min(res.h, (long long)100);
return res;
}
}zero, res;
BigInt pow(BigInt a, int i){
if(i == 0) return zero;
if(i == 1) return a;
BigInt k = pow(a, i>>1);
if(i & 1) return k*k*a;
return k*k;
}
int main()
{
scanf("%d", &n);
printf("%d\n", 1+(int)(n/log2(10)));
res.a[1] = 2;
res.h = 1;
res = pow(res, n);
res.a[1]--;
res.print();
return 0;
}