大数模版

Posted tookkke

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大数模版相关的知识,希望对你有一定的参考价值。

动态分配内存,由数的十进制位数决定。效率不是很高,但使用方便

支持负数

支持cin,cout读写

支持整形和字符串对其的初始化

支持转化为整形

能进行移位运算(<<,>>),以十进制进行移位

能进行乘方运算(^);

使用方法如下

#include <iostream>
#include "longint.h"

using namespace std;

int main()

	longint a=2;
	longint b="123";
	cout<<a<<endl;//   2
	cout<<b<<endl;//   123
	cout<<a+b<<endl;//  125
	cout<<a-b<<endl;//  -121
	cout<<a*b<<endl;//  246
	cout<<b/a<<endl;//  61
	cout<<(a<<2)<<endl;//  200
	cout<<(b>>1)<<endl;//  12
	cout<<(a^10)<<endl;//  1024
	a="-300";
	b=-1;
	int c=a.c_int();
	long long d=b.c_longlong();
	cout<<c<<endl;// -300
	cout<<d<<endl;// -1
    return 0;



(更多kkke写的模版下载,在http://pan.baidu.com/s/1c26ZuOo)

#ifndef LONGINT_H
#define LONGINT_H

#include <iostream>
#include <cstring>

class longint
	int *num;
	int len;
	bool sign;
	longint(int *new_num,int new_len,bool new_sign):num(new_num),len(new_len),sign(new_sign)
	
	
public:
	~longint();
	longint();
	longint(int a);
	longint(long long a);
	longint(const char *a);
	longint(const std::string &a);
	longint(const longint &a);
	int getlen()const;
	int c_int()const;
	long long c_longlong()const;
	friend std::ostream& operator<<(std::ostream &outs,const longint &a);
	friend std::istream& operator>>(std::istream &ins,longint &a);
	friend longint abs(longint a);
	longint operator-()const;
	const longint & operator=(const longint &a);
	const longint & operator=(int a);
	const longint & operator=(long long a);
	const longint & operator=(const char *a);
	const longint & operator=(const std::string &a);
	longint operator+(const longint &a)const;
	longint operator-(const longint &a)const;
	longint operator*(const longint &a)const;
	longint operator/(const longint &a)const;
	longint operator%(const longint &a)const;
	longint operator<<(int a)const;
	longint operator>>(int a)const;
	longint operator^(int k)const;
	const longint & operator+=(const longint &a);
	const longint & operator-=(const longint &a);
	const longint & operator*=(const longint &a);
	const longint & operator/=(const longint &a);
	const longint & operator%=(const longint &a);
	const longint & operator<<=(int a);
	const longint & operator>>=(int a);
	const longint & operator^=(int k);
	const longint & operator++();
	const longint & operator--();
	longint operator++(int);
	longint operator--(int);
	bool operator<(const longint &a)const;
	bool operator>(const longint &a)const;	
	bool operator<=(const longint &a)const;
	bool operator>=(const longint &a)const;
	bool operator!=(const longint &a)const;
	bool operator==(const longint &a)const;
;

const longint & longint::operator%=(const longint &a)

	*this=*this%a;
	return *this;


longint longint::operator%(const longint &a)const

	if(sign)return -( (-(*this)) % abs(a) );
	if(a.sign)return *this%(-a);
	if(*this<a)return *this;
	longint b=(*this)>>(len-a.len);
	while(b>=a)b-=a;
	for(int i=len-a.len-1;i>=0;i--)
	
		b=(b<<1)+(longint)num[i];
		while(b>=a)b-=a;
	
	return b;


const longint & longint::operator^=(int k)

	*this=(*this)^k;
	return *this;


longint longint::operator^(int k)const

	longint a=*this,b=1;
	while(k)
	
		if(k&1)b*=a;
		a*=a;
		k>>=1;
	
	return b;


const longint & longint::operator/=(const longint &a)

	*this=*this/a;
	return *this;


longint longint::operator/(const longint &a)const

	if(sign&&a.sign)return (-(*this))/(-a);
	if(sign||a.sign)return -(abs(*this)/abs(a));
	if(*this<a)return (longint)0;
	int new_len=len-a.len+1;
	int *new_num=new int[new_len];
	longint b=(*this)>>(len-a.len);
	new_num[new_len-1]=0;
	while(b>=a)
	
		b-=a;
		new_num[new_len-1]++;
	
	for(int i=new_len-2;i>=0;i--)
	
		b=(b<<1)+(longint)num[i];
		new_num[i]=0;
		while(b>=a)
		
			b-=a;
			new_num[i]++;
		
	
	if(!new_num[new_len-1])new_len--;
	return longint(new_num,new_len,false);


const longint & longint::operator*=(const longint &a)

	*this=*this*a;
	return *this;


longint longint::operator*(const longint &a)const

	if(len==1&&num[0]==0)return *this;
	if(a.len==1&&a.num[0]==0)return a;
	int new_len=len+a.len;
	int *new_num=new int[new_len];
	for(int i=0;i<new_len;i++)new_num[i]=0;
	for(int i=0;i<len;i++)
	    for(int j=0;j<a.len;j++)
	        new_num[i+j]+=num[i]*a.num[j];
	for(int i=0;i<new_len;i++)
	
		if(new_num[i]>=10)
		
			new_num[i+1]+=new_num[i]/10;
			new_num[i]%=10;
		
	
	if(!new_num[new_len-1])new_len--;
	return longint(new_num,new_len,(sign==a.sign)?false:true);


longint abs(longint a)

	a.sign=false;
	return a;


const longint & longint::operator<<=(int a)

	*this=(*this)<<a;
	return *this;


const longint & longint::operator>>=(int a)

	*this=(*this)>>a;
	return *this;

	
longint longint::operator>>(int a)const

	if(a>=len)return (longint)0;
	int new_len=len-a;
	int *new_num=new int[new_len];
	for(int i=0,j=a;j<len;i++,j++)new_num[i]=num[j];
	return longint(new_num,new_len,sign);


longint longint::operator<<(int a)const

	if(len==1&&num[0]==0)return *this;
	int new_len=len+a;
	int *new_num=new int[new_len];
	for(int i=0,j=a;i<len;i++,j++)new_num[j]=num[i];
	for(int i=0;i<a;i++)new_num[i]=0;
	return longint(new_num,new_len,sign);


const longint & longint::operator++()

	*this=*this+1;
	return *this;


const longint & longint::operator--()

	*this=*this-1;
	return *this;


longint longint::operator++(int)

	longint a=*this;
	*this=*this+1;
	return a;


longint longint::operator--(int)

	longint a=*this;
	*this=*this-1;
	return a;


const longint & longint::operator+=(const longint &a)

	*this=*this+a;
	return *this;


const longint & longint::operator-=(const longint &a)

	*this=*this-a;
	return *this;


int longint::getlen()const

	return len;


longint longint::operator-(const longint &a)const

	if(*this==a)return (longint)0;
	if(sign!=a.sign)return (*this)+(-a);
	if(sign)
	
		if(*this>a)return (-a) - (-(*this));
		return -( (-(*this)) - (-a) );
	
	if(*this<a)return -(a-(*this));
	int new_len=len;
	int *new_num=new int[new_len];
	new_num[0]=0;
	for(int i=0;i<a.len;i++)
	
		new_num[i]+=num[i]-a.num[i];
		if(new_num[i]<0)
		
			new_num[i]+=10;
			new_num[i+1]=-1;
		
		else if(i<len-1)new_num[i+1]=0;
	
	for(int i=a.len;i<len;i++)
	
		new_num[i]+=num[i];
		if(new_num[i]<0)
		
			new_num[i]+=10;
			new_num[i+1]=-1;
		
		else if(i<len-1)new_num[i+1]=0;
	
	while(!new_num[new_len-1])new_len--;
	return longint(new_num,new_len,false);


longint longint::operator+(const longint &a)const

	if(sign!=a.sign)return (*this)-(-a);
	if(len<a.len)return a+(*this);
	int new_len=len+1;
	int *new_num=new int[new_len];
	new_num[0]=0;
	for(int i=0;i<a.len;i++)
	
		new_num[i]+=num[i]+a.num[i];
		if(new_num[i]>=10)
		
			new_num[i]-=10;
			new_num[i+1]=1;
		
		else new_num[i+1]=0;
	
	for(int i=a.len;i<len;i++)
	
		new_num[i]+=num[i];
		if(new_num[i]>=10)
		
			new_num[i]-=10;
			new_num[i+1]=1;
		
		else new_num[i+1]=0;
	
	if(!new_num[new_len-1])new_len--;
	return longint(new_num,new_len,sign);


bool longint::operator!=(const longint &a)const

	if(sign!=a.sign)return true;
	if(len!=a.len)return true;
	for(int i=0;i<len;i++)
	    if(num[i]!=a.num[i])
	        return true;
	return false;


bool longint::operator==(const longint &a)const

	if(sign!=a.sign)return false;
	if(len!=a.len)return false;
	for(int i=0;i<len;i++)
	    if(num[i]!=a.num[i])
	        return false;
	return true;


bool longint::operator>(const longint &a)const

	return a<*this;


bool longint::operator>=(const longint &a)const

	return !(*this<a);


bool longint::operator<=(const longint &a)const

	return !(a<*this);


bool longint::operator<(const longint &a)const

	if(sign&&a.sign)
	
		if(len<a.len)return false;
	    if(len>a.len)return true;
	    for(int i=len-1;i>=0;i--)
	    
	    	if(num[i]<a.num[i])return false;
	    	if(num[i]>a.num[i])return true;
	    
	    return false;
	
	if(sign)return true;
	if(a.sign)return false;
	if(len<a.len)return true;
	if(len>a.len)return false;
	for(int i=len-1;i>=0;i--)
	
	    if(num[i]<a.num[i])return true;
	    if(num[i]>a.num[i])return false;
	
	return false;


long long longint::c_longlong()const

	long long a=0LL;
	for(int i=len-1;i>=0;i--)a=a*10LL+num[i];
	return sign?-a:a;


int longint::c_int()const

	int a=0;
	for(int i=len-1;i>=0;i--)a=a*10+num[i];
	return sign?-a:a;


longint longint::operator-()const

	if(len==1&&num[0]==0)return *this;
	longint a=*this;
	a.sign=!sign;
	return a;


const longint & longint::operator=(const std::string &a)

	return *this=a.c_str();



const longint & longint::operator=(int a)

	if(num)delete[] num;
	if(!a)
	
		num=new int[1];
		num[0]=0;
		len=1;
		sign=false;
		return *this;
	
	num=new int[20];
	if(a<0)
	
		sign=true;
		a=-a;
	
	else sign=false;
	len=0;
	while(a)
	
		num[len]=a%10;
		len++;
		a/=10;
	
	return *this;



const longint & longint::operator=(long long a)

	if(num)delete[] num;
	if(!a)
	
		num=new int[1];
		num[0]=0;
		len=1;
		sign=false;
		return *this;
	
	num=new int[40];
	if(a<0LL)
	
		sign=true;
		a=-a;
	
	else sign=false;
	len=0;
	while(a)
	
		num[len]=a%10LL;
		len++;
		a/=10LL;
	
	return *this;


const longint & longint::operator=(const char *a)

	if(a[0]=='-')
	
		sign=true;
		a++;
	
	else sign=false;
	len=strlen(a);
	if(num)delete[] num;
	num=new int[len];
	for(int i=0,j=len-1;i<len;i++,j--)num[i]=a[j]-'0';
	return *this;


const longint & longint::operator=(const longint &a)

	if(num)delete[] num;
	num=new int[a.len];
	sign=a.sign;
	len=a.len;
	for(int i=0;i<len;i++)num[i]=a.num[i];
	return *this;


longint::longint()

	num=NULL;


longint::~longint()

    if(num)delete[] num;


longint::longint(const char *a)

	if(a[0]=='-')
	
		sign=true;
		a++;
	
	else sign=false;
	while(*a=='0'&&a[1])a++;
	len=strlen(a);
	num=new int[len];
	for(int i=0,j=len-1;i<len;i++,j--)num[i]=a[j]-'0';


longint::longint(int a)

	if(!a)
	
		num=new int[1];
		num[0]=0;
		len=1;
		sign=false;
		return;
	
	num=new int[20];
	if(a<0)
	
		sign=true;
		a=-a;
	
	else sign=false;
	len=0;
	while(a)
	
		num[len]=a%10;
		len++;
		a/=10;
	


longint::longint(long long a)

	if(!a)
	
		num=new int[1];
		num[0]=0;
		len=1;
		sign=false;
		return;
	
	num=new int[40];
	if(a<0)
	
		sign=true;
		a=-a;
	
	else sign=false;
	len=0;
	while(a)
	
		num[len]=a%10;
		len++;
		a/=10;
	


longint::longint(const std::string &a)

	num=NULL;
	*this=a.c_str();


longint::longint(const longint &a)

	num=new int[a.len];
	sign=a.sign;
	len=a.len;
	for(int i=0;i<len;i++)num[i]=a.num[i];


std::ostream& operator<<(std::ostream &outs,const longint &a)

	if(a.sign)outs<<'-';
	for(int i=a.len-1;i>=0;i--)outs<<a.num[i];
	return outs;


std::istream& operator>>(std::istream &ins,longint &a)

	std::string data;
	ins>>data;
	a=data;
	return ins;


#endif //#ifndef LONGINT_H





    上面的乘法直接用的普通O(n^2)的方法,还有一种递归实现的O(n^(1.5))的方法,不过实际情况看来并没有多大优化,而且很占空间。

    思想就是每次将两个数分别分成前半部分和后半部分,两两分别相乘,递归处理,直到位数小于一定值就直接转换为int型再乘。

longint longint::operator*(const longint &a)const

	if(len<9&&a.len<9)return c_longlong()*a.c_longlong();
	if(len==1&&num[0]==0)return *this;
	if(a.len==1&&a.num[0]==0)return a;
	int n=std::max(len,a.len)>>1;
	//XY=AC<<2n+[(A-B)(D-C)+AC+BD]<<n+BD;
	longint A=(*this)>>n;
	longint B=(*this)-(A<<n);
	longint C=a>>n;
	longint D=a-(C<<n);
	longint AC=A*C;
	longint BD=B*D;
	return (AC<<(2*n))+( ( (A-B)*(D-C)+AC+BD ) <<n)+BD;

    学了FFT,发现大数乘法使用FFT会更快(O(log n)),并且我还发现了这个模版确实有很多不足的地方,也许会在一段时间之内改进吧。


以上是关于大数模版的主要内容,如果未能解决你的问题,请参考以下文章

大数处理 详解 模版

数论 (大数,小费马定理,欧拉定理,威尔逊定理,快速数论变换(NNT)模版)

L1-046 整除光棍 [大数相除]

BZOJ 3110 [Zjoi2013]K大数查询

HDU 1402 A * B Problem Plus FFT+convert

python numpy array 与matrix 乘方