【基础算法】大整数运算

阶乘之和(高精度)题目描述

#include<iostream>
#include<cstring>
using namespace std;
#define maxn 100

struct Bigint {
	int len, a[maxn];
	Bigint(int x = 0) {  //构造函数,进行初始化 
		memset(a, 0, sizeof(a));
		for(len = 1; x; len++) { //x由循环内执行改变,为0时跳出循环
			a[len] = x % 10;
			x /= 10;
		} 
		len--;
	}
	
	int &operator[](int i) { //重载[],直接用x[i]代表x.a[i] 
		return a[i];
	}
	
	void flatten(int l) { //处理1到l范围内的进位并重置长度 
	    len = l;
	    for(int i = 1; i <= len; i++) {
	    	a[i + 1] += a[i] / 10;
	    	a[i] %= 10;
		}
		for(; !a[len]; ) len--; //l涉及进位,不是有效长度,处理后可能存在剩余0,需要重置长度为有效长度
	}
	
	void print() {
		for(int i = max(1, len); i >= 1; i--) printf("%d", a[i]);
	}
}; 

Bigint operator+(Bigint a, Bigint b) { //表示两个 Bigint类相加 
	Bigint c;
	int len = max(a.len, b.len);
	for(int i = 1; i <= len; i++) 
		c[i] = a[i] + b[i];
	c.flatten(len + 1); //两者相加进位后不超过len+1
	return c;
}

Bigint operator*(Bigint a, int b) { //表示Bigint类乘整型变量 
	Bigint c;
	int len = a.len;
	for(int i = 1; i <= len; i++) 
		c[i] = a[i] * b;
	c.flatten(len + 11); // len+11满足大整数相乘进位 
	return c;
}

int main() {
	Bigint ans(0), fac(1); //分别用0和1初始化ans和fac 
	int m;
	cin >> m;
	for(int i = 1; i <= m; i++) { 
		fac = fac * i;
		ans = ans + fac; 
	}
	ans.print();
    return 0;
}

 大整数重载减号进行数组运算

Bigint operator-(Bigint z, Bigint b) { 
	Bigint c;
	int len = z.len;
	for(int i = 1; i <= len; i++) {
		if(z[i] < b[i]) {
			z[i] += 10;
			z[i+1] -= 1;
		}
		c[i] = z[i] - b[i];
	}
	c.len = len;
	for(; !c[len]; ) c.len--;
	return c;
}

  大整数重载乘号进行数组运算

Bigint operator*(Bigint a, Bigint b) { 
	Bigint c;
	int lena = a.len, lenb = b.len;
	for(int i = 1; i <= lena; i++) {
		for(int j = 1; j <= lenb; j++) 
		    c[i + j - 1] += a[i] * b[j]; 
	}
	c.flatten(lena + lenb); 
	return c;
}

 麦森数题目描述

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define MAXN 100001
#define POST 500
 
struct Bigint {
	int len, a[MAXN];
	Bigint(int x = 0) { 
		memset(a, 0, sizeof(a));
		for(len = 1; x; len++) { 
			a[len] = x % 10;
			x /= 10;
		} 
		len--;
	}
	
	int &operator[](int i) { 
		return a[i];
	}
	
	void flatten(int l) { 
	    len = l;
	    for(int i = 1; i <= len; i++) {
	    	a[i + 1] += a[i] / 10;
	    	a[i] %= 10;
		}
		for(; !a[len]; ) len--; 
	}
	
	void print() {
		for (int i = POST; i >= 1; --i) {
            printf("%d", a[i]);
            if (!((i-1) % 50 )) printf("\n");
       }
	}
}; 
 
Bigint operator*(Bigint a, Bigint b) { 
	Bigint c;
	int lena = min(POST, a.len), lenb = min(POST, b.len);
	for(int i = 1; i <= lena; i++) {
		for(int j = 1; j <= lenb; j++) 
		    c[i + j - 1] += a[i] * b[j]; 
	}
	c.flatten(lena + lenb); 
	return c;
}

//​采用了高精和快速幂方法 
int main() {
	Bigint res(1), f(2);
	int p;
	cin >> p;
	printf("%d\n", (int)(log10(2)*p+1));
    while(p != 0) {
        if(p % 2 == 1) //等同于n&1, 如果n的当前末位为1 
		    res = res * f;  
        p /= 2;  //等同于n >>= 1, n往右移一位
        f = f * f;
    }
    res[1] -= 1;
	res.print();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超级码立

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值