NOIP学习小站
西安交通大学附属中学航天学校

*高精度运算——结构体实现

来看问题:P1009阶乘之和

根据数据规模可以明显看出这里需要使用高精度运算。可以将高精度正整数封装成一个结构体,通过重载运算符来实现高精度正整数的四则运算,下面给出参考代码,但是涉及到C++的一些高级用法,理解起来有一定难度:

#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1000;
struct BigInt{
	//arr[0]存储位数,arr[1]、arr[2]、…从低到高位依次存储高精度正整数每位上的数字 
	int arr[MAXN+10];
	
	//构造函数(long long参数x默认值为0) 
	BigInt(long long x = 0){
		memset(arr,0,sizeof(arr));
		for(int i=1;x;i++){
			arr[0]++;
			arr[i] = x%10;
			x /= 10;
		}
	}
	
	//重载[]运算符,重载后对于BigInt类型变量x,可以直接用x[i]替代x.arr[i] 
	int &operator [] (int i){ 
		return arr[i]; 
	}
	
	//判断是否等于0 
	bool isZero() const{	//const表示成员函数内部不能修改任何成员变量 
		return arr[0]<=1 && arr[1]==0;
	}

	//重载=运算符,实现BigInt变量赋值为int 
	BigInt& operator = (int n){
	    *this = BigInt(n);
	    return *this;
	}
};

//重载+运算符,实现BigInt+BigInt 
BigInt operator + (BigInt a,BigInt b){
	BigInt r;
	int x = 0;
	for(int i=1;i<=a[0] || i<=b[0];i++){
		r[0]++;
		r[i] = a[i]+b[i]+x;
		if(r[i]>=10) x=1,r[i]-=10;
		else x=0;
	}
	if(x) r[++r[0]] = x;
	return r;
}

//重载+=运算符,实现BigInt+BigInt 
BigInt& operator += (BigInt& a,BigInt& b){
    int x = 0,size = 0;
    for(int i=1;i<=a[0] || i<=b[0];i++){
        size++;
        a[i] +=b[i]+x;
        if(a[i]>=10) x=1,a[i]-=10;
        else x=0;
    }
    a[0] = size;
    if(x) a[++a[0]] = x;
    return a;
}

//重载*运算符,实现BigInt*long long 
BigInt operator * (BigInt a,long long b){
	BigInt r;
	if(a.isZero() || b==0) return r;
	
	long long x = 0,y;
	for(int i=1;i<=a[0];i++){
		r[0]++;
		y = a[i]*b+x;
		r[i] = y%10;
		x = y/10;
	}
	while(x) r[++r[0]] = x%10,x /= 10;
	return r;
}

//重载*=运算符,实现BigInt*long long
BigInt& operator *= (BigInt& a,long long b){
    if(a.isZero() || b==0) {
        a[0] = 1, a[1] = 0;
        return a;
    }
    long long x = 0,y;
    for(int i=1;i<=a[0];i++){
        y = a[i]*b+x;
        a[i] = y%10;
        x = y/10;
    }
    while(x) a[++a[0]] = x%10,x /= 10;
    return a;
}

//重载ostream运算符,可以直接用cout输出BigInt变量 
ostream& operator << (ostream &os,BigInt &bi){
	for(int i=max(bi[0],1);i>=1;i--) os<<bi[i];
	return os;
}

int main()
{
	BigInt ans = 0,fac = 1;
	
	int n;
	cin>>n;
	
	for(int i=1;i<=n;i++){
		fac = fac*i;     // fac *= i;
		ans = ans+fac;   // ans += fac;
	}
	
	cout<<ans<<endl;
	return 0;
} 

通过封装结构体,主函数内高精度正整数的加法和乘法运算可以像普通的整型变量那样简便。可以对比下面用long long数据类型计算阶乘累加和的程序:

#include<iostream>
using namespace std;
int main()
{
    long long ans = 0,fac = 1;
    
    int n;
    cin>>n;
    
    for(int i=1;i<=n;i++){
        fac = fac*i;     // fac *= i;
        ans = ans+fac;   // ans += fac;
    }
    
    cout<<ans<<endl;
    return 0;
}