高精度封装版
注意事项:
unsigned Bignum
.- 减法必须保证 \(a \ge b\).
- 暂时没有 高精 除 高精
- 没有压位,较慢。
- 我吐了,ntt 不支持压位。
代码:
namespace Bignum
{
// # Bignum using vector as base
// Done in 2021.2.9 by cjlworld
typedef long long LL;
typedef vector<LL> vint;
vint operator+(vint a,LL b);
vint operator+(vint a,vint b);
vint operator-(vint a,vint b);
vint operator-(vint a,vint b);
vint operator*(vint a,vint b);
vint operator*(vint a,LL b);
vint operator/(vint a,LL b);
vint operator/(vint a,vint b);
LL operator%(vint a,LL b);
vint power(vint x,LL k);
bool operator<(const vint& a,const vint& b);
bool operator<=(const vint& a,const vint& b);
bool operator>=(const vint& a,const vint& b);
bool operator>(const vint& a,const vint& b);
// ## calc +,-,*,/,^,%,
// ### +
// #### vint + LL
vint operator+(vint a,LL b)
{
for(int i=0;i<(int)a.size() && b;i++) {
b+=a[i];
a[i]=b%10;
b/=10;
}
while(b) a.push_back(b%10),b/=10;
return a;
}
// #### vint+vint
vint operator+(vint a,vint b)
{
vint c;
int t=0;
if(a.size()<b.size()) swap(a,b);
for(int i=0;i<(int)a.size();i++) {
t+=a[i];
if(i<(int)b.size()) t+=b[i];
c.push_back(t%10);
t/=10;
}
if(t) c.push_back(t);
return c;
}
// ### -
vint operator-(vint a,vint b)
{
for(int i=0;i<(int)b.size();i++) {
if(a[i]<b[i]) {
a[i+1]--;
a[i]+=10;
}
a[i]-=b[i];
}
for(int i=0;i<(int)a.size();i++) {
if(a[i]<0) {
a[i]+=10;
a[i+1]--;
}
}
while(a.size()>1 && !a.back()) a.pop_back();
return a;
}
// ### *
// #### using ntt
const int _N=4e5+5;
const LL _P=998244353,_G=3;
LL power(LL x,LL k,LL MOD)
{
LL res=1; x%=MOD;
while(k) {
if(k&1) res=res*x%MOD;
x=x*x%MOD; k>>=1;
}
return res%MOD;
}
int rev[_N];
void ntt(LL a[],int n,int inv)
{
for(int i=0;i<n;i++)
if(rev[i]<i) swap(a[rev[i]],a[i]);
for(int k=2,m=1;k<=n;m=k,k<<=1) {
LL gn=power(_G,(_P-1)/k,_P);
if(inv==-1) gn=power(gn,_P-2,_P);
for(int i=0;i<n;i+=k) {
LL g=1;
for(int j=0;j<m;j++,g=g*gn%_P) {
LL u=a[i+j],v=a[i+j+m];
a[i+j]=u+g*v; a[i+j+m]=u-g*v;
}
}
for(int i=0;i<n;i++) a[i]=(a[i]%_P+_P)%_P;
}
if(inv==-1) {
for(int i=0;i<n;i++)
a[i]=a[i]*power(n,_P-2,_P)%_P;
}
}
// #### vint*vint
vint operator*(vint a,vint b)
{
static LL A[_N],B[_N];
static vint c; c.clear();
for(int i=0;i<(int)a.size();i++) A[i]=a[i];
for(int i=0;i<(int)b.size();i++) B[i]=b[i];
int tot=a.size()+b.size(),bit=1;
while((1<<bit)<tot) bit++;
tot=(1<<bit);
for(int i=0;i<tot;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
ntt(A,tot,1); ntt(B,tot,1);
for(int i=0;i<tot;i++) A[i]=A[i]*B[i]%_P;
ntt(A,tot,-1);
LL t=0;
for(int i=0;i<tot;i++) {
t+=A[i];
A[i]=t%10;
t/=10;
}
for(int i=0;i<(int)(a.size()+b.size());i++)
c.push_back(A[i]);
while(!c.back() && c.size()>1) c.pop_back();
for(int i=0;i<tot;i++) A[i]=B[i]=rev[i]=0; // 别忘了清空。
return c;
}
// #### vint * LL
vint operator*(vint a,LL b)
{
vint c;
LL t=0;
for(int i=0;i<(int)a.size();i++) {
t+=a[i]*b;
c.push_back(t%10);
t/=10;
}
while(t) c.push_back(t%10),t/=10;
while(c.size()>1 && !c.back()) c.pop_back();
return c;
}
// ### /
// #### vint / LL
vint operator/(vint a,LL b)
{
vint c;
int t=0;
for(int i=a.size()-1;i>=0;i--) {
t=(t<<1)+(t<<3)+a[i];
c.push_back(t/b);
t%=b;
}
reverse(c.begin(),c.end());
while(c.size()>1 && !c.back()) c.pop_back();
return c;
}
// ### vint / vint
vint operator/(vint a,vint b)
{
if(a<b) return vint(1,0);
vint t=b; LL bit=0;
while(t<a) t.insert(t.begin(),0),bit++;
vint c(bit+1);
for(;bit>=0;bit--) {
while(a>=t) a=a-t,c[bit]++;
t.erase(t.begin());
}
while(c.size()>1 && !c.back()) c.pop_back();
return c;
}
// ### %
LL operator%(vint a,LL b)
{
LL t=0;
for(int i=a.size()-1;i>=0;i--)
t=(t*10+a[i])%b;
return t;
}
// ### ^
vint power(vint x,LL k)
{
vint res; res.push_back(1);
while(k) {
if(k&1) res=res*x;
x=x*x; k>>=1;
}
return res;
}
// ## Compare
// ### < is basic
bool operator<(const vint& a,const vint& b)
{
if(a.size()!=b.size()) return (a.size()<b.size());
for(int i=a.size()-1;i>=0;i--)
if(a[i]!=b[i]) return (a[i]<b[i]);
return false;
}
// ### == is basic too, but it has been done
// ### > , <= , >=
bool operator<=(const vint& a,const vint& b) { return a<b || a==b; }
bool operator>=(const vint& a,const vint& b) { return !(a<b); }
bool operator>(const vint& a,const vint& b) { return !(a<=b); }
// ## in and out。
// ### in
istream &operator>>(istream& cin,vint& v)
{
static string s;
v.clear();
cin>>s;
reverse(s.begin(),s.end());
for(int i=0;i<(int)s.length();i++)
v.push_back(s[i]-'0');
return cin;
}
// out
ostream &operator<<(ostream& cout,vint v)
{
for(int i=v.size()-1;i>=0;i--) cout<<v[i];
return cout;
}
}
using namespace Bignum;