大数模版
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)模版)