记录编号 192106 评测结果 AAAAAAAAAA
题目名称 [NOIP 2003]麦森数 最终得分 100
用户昵称 Gravatar啊吧啦吧啦吧 是否通过 通过
代码语言 C++ 运行时间 1.419 s
提交时间 2015-10-09 19:44:59 内存使用 0.28 MiB
显示代码纯文本
/*提示 
l第一问是很简单的,只需要求一个对数而已,数学原理:十进制正整数n的位数为int(log10(n))+1。所以2^P-1的位数int(log10(2)^p)+1 = int(p*log10(2))+1 。 
l即int(p*(ln2/ln10))+1 
l本题的解题方法很多,其中分治也是一种巧妙的方法。首先可以想到: 
  2n=(2 n div 2)2*2 (n mod 2) ,即:如果要计算2n,就要先算出2 n div 2,然后用高精度乘法算它的平方,如果n是奇数还要再乘以2,写成递归公式就是:f(n)=(f(n div 2))2*2(n mod 2)。 
当然,递归是要有边界值的,这就是当n=0时,f(n)=1。还要补充一点,该数的长度是可以用公式计算的,所以在做高精度乘法时,只要取最后500位运算就行了。*/
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <cstdio>
#include <fstream>
  
using namespace std;
 
string num;
char s[10];
int p, w = 0, g[129] = {0}, nw = 1;
inline void gaojing(); 
 
main()
{
	freopen("mason.in", "r", stdin);
	freopen("mason.out", "w", stdout);
	int i;
	g[1] = 1;
	cin >> p;
	for (i = 1; i <= p; i++)
		gaojing();
	--g[1];
	w = (p * (log(2) / log(10))) + 1;
	printf("%d\n", w);
	g[63] %= 10000;
	sprintf(s, "%04d", g[63]);
	num += s;
	for (i = 62; i > 0; i--){
		sprintf(s, "%08d", g[i]);
		num += s;
	}
	for (int i = 0; i < 500; i++){
		cout << num[i];
		if(i==49||i==99||i==149||i==199||i==249||i ==299||i==349||i==399||i==449||i==499)
		    cout << endl;
	}
	fclose(stdin);
	fclose(stdout);
//	for (; ; );
}
 
 
inline void gaojing(){
	int i = 1, x = 0;
	while (i <= min(63, nw + 5)){
		g[i] = x + g[i] * 2;
		x = g[i] / 100000000;
		g[i] %= 100000000;
		i++;
		if (i > nw && g[i] != 0)
			nw++;
	}
	x = 0;
}