【洛谷训练】麦森数

题目链接:麦森数

首先,写在最前面:这道题要用“快速幂算法”。
我一开始以为只是高精度乘法+减一(其实后来发现二次幂的个位数不可能为0,直接减一即可)+补足(其实这个也不需要,只需要在高精度乘法中控制位数为500,高位就会默认补0)
然后用这个方法后,有四个点TLE(我一开始还在想会不会是string位数不够,但是这种情况的话应该是爆内存,而不是超时,并且string长度一般来说是够的)
因此,在看了大佬的题解后,学习了快速幂算法。
以下这段代码几个需要注意的点:
1.11-12行:i和j都控制在500以下,反正最后只需要输出后500位。如果输出大于500位数,不会影响到计算。当然,如果输出小于500位数,这样子还能做到高位默认补0。(一举两得)
2.学习了 memset和memcpy两个函数,以后要常用,比for循环简单多了。
3.40行:计算位数,log函数的头文件#include<cmath
4. 43-47行:快速幂算法:如果指数是奇数,作ans=ans*a(底数),使得指数减一,变成偶数。然后指数除2,指数平方(可以找视频复习更快)。
5.49-52行:最后的输出记得倒序输出。

#include<iostream>
#include<cstring>
#include<cmath>
#define MAXN 2000
typedef long long ll;
int num[MAXN],f[MAXN],sum[MAXN];
ll len,n;
void mul_1()
{
	memset(sum,0,sizeof(sum));
	for(ll i=1;i<=500;i++)
		for(ll j=1;j<=500;j++)
			sum[i+j-1]+=num[i]*f[j];
	for(ll i=1;i<=500;i++){
		if(sum[i]>=10){
			sum[i+1]+=sum[i]/10;
			sum[i]%=10;
		}
	}
	memcpy(num,sum,sizeof(num));
}		
void mul_2()
{
	memset(sum,0,sizeof(sum));
	for(ll i=1;i<=500;i++)
		for(ll j=1;j<=500;j++)
			sum[i+j-1]+=f[i]*f[j];
	for(ll i=1;i<=500;i++){
		if(sum[i]>=10){
			sum[i+1]+=sum[i]/10;
			sum[i]%=10;
		}
	}
	memcpy(f,sum,sizeof(f));	
 } 
using namespace std;
int main(void)
{
	cin>>n;
	cout<<(int)(log10(2)*n+1)<<endl;
	num[1]=1;
	f[1]=2;
	while(n>0){//快速幂 
		if(n&1) mul_1();
		n>>=1;
		mul_2();	
	}
	num[1]-=1;
	for(int i=500;i>=1;i--){
		if(i%50==0&&i!=500) cout<<endl;
		cout<<num[i];	
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值