模版大全
__Alex866__
·
·
个人记录
提示
- 部分代码又臭又长,请谨慎阅读。
- 最好使用 PgUp 和 PgDn 键浏览。
经典火车头
#include<bits/extc++.h>
//#define ONLINE_JUDGE
#define _INT_TO_LL
#define _CLOSE_SYNC
//#define _USE_FREOPEN
#if 1
using namespace std;
using namespace chrono;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
using ui32=unsigned int;
using i64=long long;
using ui64=unsigned long long;
using i128=__int128;
using ui128=unsigned __int128;
using f64=double;
using f128=long double;
template<typename _Type> _Type __lcm(_Type a,_Type b){
return a/__gcd(a,b)*b;
}
template<typename _Type>
string YN(_Type a,int b=1){
return a?(b&2?"YES":b&1?"Yes":"yes"):(b&2?"NO":b&1?"No":"no");
}
template<typename Array,typename _Type>
void mem(Array &arr,const _Type &value){
typename remove_all_extents<Array>::type typedef ElementType;
fill_n(reinterpret_cast<ElementType*>(&arr),sizeof(arr)/sizeof(ElementType),static_cast<ElementType>(value));
}
template<typename Array>
void clr(Array &arr){
typename remove_all_extents<Array>::type typedef ElementType;
mem(arr,ElementType(0));
}
template<typename Array>
void neg(Array &arr){
typename remove_all_extents<Array>::type typedef ElementType;
mem(arr,ElementType(-1));
}
template<typename Array>
void fmax(Array &arr){
typename remove_all_extents<Array>::type typedef ElementType;
mem(arr,numeric_limits<ElementType>::max());
}
template<typename Array>
void fmax_s(Array &arr){
typename remove_all_extents<Array>::type typedef ElementType;
mem(arr,numeric_limits<ElementType>::max()/2);
}
template<typename Array>
void fmin(Array &arr){
typename remove_all_extents<Array>::type typedef ElementType;
mem(arr,numeric_limits<ElementType>::min());
}
template<typename Array>
void fmin_s(Array &arr){
typename remove_all_extents<Array>::type typedef ElementType;
mem(arr,numeric_limits<ElementType>::min()/2);
}
mt19937_64 _Random(system_clock::now().time_since_epoch().count());
template<typename _Type>
_Type _Rand(_Type l,_Type r){
return uniform_int_distribution<_Type>(l,r)(_Random);
}
template<typename _Type>
void srand(_Type _Seed){
_Random.seed(_Seed);
}
int rand(){
return _Rand(0,RAND_MAX);
}
template<typename _Type,typename _Compare>
using _CPQ=std::priority_queue<_Type,vector<_Type>,_Compare>;
template<typename _Type>
using _GPQ=_CPQ<_Type,greater<>>;
template<typename _Type>
using _PQ=std::priority_queue<_Type>;
template<typename _Key,typename _Type>
using _MM=multimap<_Key,_Type>;
template<typename _Type>
using _MS=multiset<_Type>;
template<typename _Type>
using _P=pair<_Type,_Type>;
template<typename _Key,typename _Type>
using _UM=unordered_map<_Key,_Type>;
template<typename _Type>
using _US=unordered_set<_Type>;
template<typename _Key,typename _Type>
using _UMM=unordered_multimap<_Key,_Type>;
template<typename _Type>
using _UMS=unordered_multiset<_Type>;
template<typename _Type>
using _V=vector<_Type>;
constexpr ui64 HashP=1313131313131313131ull,HashP1=1111111111111111171ull,HashP2=37093201209218101ull,HashP3=3113333333333333333ull,HashP4=4444444444444444409ull,HashP5=370903201209218177ull;
constexpr int mod3=998244353,mod7=1000000007,mod9=1000000009,d4[4][2]={{0,1},{1,0},{0,-1},{-1,0}},d8[8][2]={{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
istream& operator>>(istream& in,i128& a){
a=0;
char ch;
bool fl;
while(isspace((in.get(ch),ch)));
fl=(ch==45?ch=in.get(),1:0);
while(isdigit(ch)){
(a*=10)+=ch^48;
in.get(ch);
}
if(fl){
a=-a;
}
return in;
}
istream& operator>>(istream& in,ui128& a){
a=0;
char ch;
while(isspace((in.get(ch),ch)));
while(isdigit(ch)){
(a*=10)+=ch^48;
in.get(ch);
}
return in;
}
ostream& operator<<(ostream& out,const i128& a){
if(a<0){
out<<'-';
out<<-a;
return out;
}
if(a<10){
out<<char(a^48);
return out;
}
out<<a/10;
return out<<a%10;
}
ostream& operator<<(ostream& out,const ui128& a){
if(a<10){
out<<char(a^48);
return out;
}
out<<a/10;
return out<<a%10;
}
#define y0 __Y0_By_MySelf__
#define y1 __Y1_By_MySelf__
#define yn __Yn_By_MySelf__
#define j0 __J0_By_MySelf__
#define j1 __J1_By_MySelf__
#define jn __Jn_By_MySelf__
#define _FF(_Name,_Begin,_End) for(auto _Name=(_Begin);_Name<(_End);_Name++)
#define _RF(_Name,_Begin,_End) for(auto _Name=(_Begin)-1;_Name>=(_End);_Name--)
#define _FE(_Container,...) for(auto __VA_ARGS__:_Container)
#define _SP(_Digit) fixed<<setprecision(_Digit)
#define _Max(...) max({__VA_ARGS__})
#define _Min(...) min({__VA_ARGS__})
#define tostr(_Name) std::to_string(_Name)
#ifndef ONLINE_JUDGE
void pt(){
cerr<<endl;
}
template<typename _Slipt,typename _End,typename _Type>
void pt(_Slipt,_End end,_Type a){
cerr<<a<<end;
}
template<typename _Slipt,typename _End,typename _Type,typename... _Args>
void pt(_Slipt slipt,_End end,_Type a,_Args ...args){
cerr<<a<<slipt;
pt(slipt,end,args...);
}
template<typename... _Args>
void psp(_Args ...args){
pt(' ',' ',args...);
}
template<typename... _Args>
void pln(_Args ...args){
pt(' ','\n',args...);
}
template<typename _Type>
void __psth(_Type line){
static int cnt;
pt("","","\n-------------------------No.",cnt," Line:",line,"-------------------------\n");
cnt++;
}
#define psth() __psth(__LINE__)
#else
#define pt(...)
#define psp(...)
#define pln(...)
#define psth(...)
#define __psth(...)
#endif
#ifdef _INT_TO_LL
#define int i64
#define INT_MAX LLONG_MAX
#define INT_MIN LLONG_MIN
#endif
using _Pi=_P<int>;
using _Vi=_V<int>;
using _Vpi=_V<_Pi>;
#endif
signed main(){
ifdef _CLOSE_SYNC
cin.tie(0)->sync_with_stdio(0);
endif
ifdef _USE_FREOPEN
ifstream fin(".in");
ofstream fout(".out");
cin.rdbuf(fin.rdbuf());
cout.rdbuf(fout.rdbuf());
endif
return 0;
}
## 随机数(建议背过)
```cpp
mt19937 rd(chrono::system_clock::now().time_since_epoch().count());
卡常 & 函数
卡常小技巧
ull gcd(ull x,ull y){
if(!x){
return y;
}
if(!y){
return x;
}
int t=__builtin_ctz(x|y);
x>>=__builtin_ctz(x);
do{
y>>=__builtin_ctz(y);
if(x>y){
swap(x,y);
}
y-=x;
}while(y);
return x<<t;
}
ll gcd(ll x,ll y){
if(!x){
return y;
}
if(!y){
return x;
}
int t=__builtin_ctzll(x|y);
x>>=__builtin_ctzll(x);
do{
y>>=__builtin_ctzll(y);
if(x>y){
swap(x,y);
}
y-=x;
}while(y);
return x<<t;
}
bool is_odd(ll x){ //奇数
return ~x&1;
}
bool is_odd(ull x){ //奇数
return ~x&1;
}
bool is_even(ll x){ //偶数
return x&1;
}
bool is_even(ull x){ //偶数
return x&1;
}
bool int_greater(int x,int y){ //大于
return((uint)(y)-(uint)(x))>>31;
}
bool uint_greater(uint x,uint y){ //大于
return(y-x)>>31;
}
bool ll_greater(ll x,ll y){ //大于
return((ull)(y)-(ull)(x))>>63;
}
bool ull_greater(ull x,ull y){ //大于
return(y-x)>>63;
}
bool opposite(ll x){ //相反数
return ~x+1;
}
bool opposite(ull x){ //相反数
return ~x+1;
}
int int_abs(int x){
return x^(~(x>>31)+1)+(x>>31);
}
ll ll_abs(ll x){
return x^(~(x>>63)+1)+(x>>63);
}
template <typename T>
void data_swap(T &x,T &y){
x^=y^=x^=y;
}
奇奇怪怪的函数
template <typename T>
double log(T n,T di){
return log(n)/log(di);
}
void printFloatBits(float value) {
unsigned long long bits=*reinterpret_cast<unsigned long long*>(&value);
bitset<sizeof(float)*CHAR_BIT> binary(bits);
for(int i=binary.size()-1;i>=0;i--){
cout<<binary[i];
if(i%8==0){
cout<<' ';
}
}
}
void printDoubleBits(double value) {
unsigned long long bits=*reinterpret_cast<unsigned long long*>(&value);
bitset<sizeof(double)*CHAR_BIT> binary(bits);
for(int i=binary.size()-1;i>=0;i--){
cout<<binary[i];
if(i%8==0){
cout<<' ';
}
}
}
void printLongDoubleBits(long double value) {
unsigned char* bytes=reinterpret_cast<unsigned char*>(&value);
for (int i=0;i<sizeof(long double);i++){
bitset<CHAR_BIT> binary(bytes[i]);
cout<<binary<<" ";
}
}
double test_time(){
LARGE_INTEGER nFreq;
LARGE_INTEGER nBeginTime;
LARGE_INTEGER nEndTime;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);//开始计时
//TODO
QueryPerformanceCounter(&nEndTime);//停止计时
return double(nEndTime.QuadPart-nBeginTime.QuadPart)/(double)nFreq.QuadPart;//计算程序执行时间单位为s
}
void rgb_init(){ //调整控制台颜色
HANDLE hIn=GetStdHandle(STD_INPUT_HANDLE);
HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dwInMode,dwOutMode;
GetConsoleMode(hIn,&dwInMode);
GetConsoleMode(hOut,&dwOutMode);
dwInMode|=0x0200;
dwOutMode|=0x0004;
SetConsoleMode(hIn,dwInMode);
SetConsoleMode(hOut,dwOutMode);
}
void rgb_set(int wr,int wg,int wb,int br,int bg,int bb){
printf("\033[38;2;%d;%d;%dm\033[48;2;%d;%d;%dm",wr,wg,wb,br,bg,bb);
}
void messy(){
srand(time(0));
while(1){
for(long long i=1;i<=rand()%100+1;i++){
int x=rand()%3;
if(x==0){
rgb_set(rand()%256,rand()%256,rand()%256,rand()%256,rand()%256,rand()%256);
cout<<rand();
fflush(stdout);
Sleep(rand()%3);
}
if(x==1){
for(long long i=1;i<=rand()%100+1;i++){
rgb_set(rand()%256,rand()%256,rand()%256,rand()%256,rand()%256,rand()%256);
cout<<(char)(rand()%128);
fflush(stdout);
Sleep(rand()%3);
}
}
if(x==2){
for(long long i=1;i<=rand()%10+1;i++){
rgb_set(rand()%256,rand()%256,rand()%256,rand()%256,rand()%256,rand()%256);
cout<<" ";
fflush(stdout);
Sleep(rand()%3);
}
}
Sleep(rand()%10);
}
for(long long i=1;i<=rand()%3+1;i++){
cout<<endl;
Sleep(rand()%3);
}
}
}
快速幂
ll fastPow(ll a,ll n,ll m){
a%=m;
if(n==0||a==1){
return 1;
}
if(n==1){
return a;
}
ll ans=1,s=a;
while(n){
if(n&1){
ans=ans*s%m;
}
s=s*s%m;
n>>=1;
}
return ans;
}
ull fastPow(ull a,ull n,ull m){
a%=m;
if(n==0||a==1){
return 1;
}
if(n==1){
return a;
}
ull ans=1,s=a;
while(n){
if(n&1){
ans=ans*s%m;
}
s=s*s%m;
n>>=1;
}
return ans;
}
二分
bool chack(/*Something*/){
//TODO
return /*Value*/0;
}
int binarySearch(/*Something*/){
int l=0,r=1e9/*Max*/,mid; //l:满足条件
while(l<=r){
mid=(l+r)/2;
if(chack(/*Something*/)){ //不满足
l=mid+1;
}else{
r=mid-1;
}
}
return r;
}
三分
while(l<=r){
mid=(r-l)/3;
if(check(l+mid)<check(r-mid)){
r-=mid+1e-9;
}else{
l+=mid+1e-9;
}
}
并查集
int fa[1005],rnk[1005];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
x=find(x);
y=find(y);
if(x==y){
return;
}
if(rnk[x]==rnk[y]){
if(rand()&1){
fa[x]=y;
rnk[y]+=rnk[x];
}else{
fa[y]=x;
rnk[x]+=rnk[y];
}
}else if(rnk[x]<rnk[y]){
fa[x]=y;
rnk[y]+=rnk[x];
}else{
fa[y]=x;
rnk[x]+=rnk[y];
}
}
01分数规划
同二分。二分\frac{\sum a_i}{\sum b_i}
数据结构
单调队列
//优先队列用priority_queue
template <typename T>
class monotonicQueueC{
private:
deque<T>dq;
unsigned maxlen;
public:
monotonicQueueC(int len=0):maxlen(len){
dq.clear();
}
void push(T a){
while(dq.size()&&dq.back()>a){
dq.pop_back();
}
dq.push_back(a);
if(dq.size()>maxlen){
while(dq.size()&&dq.size()>maxlen){
dq.pop_back();
}
}
}
void pop(){
dq.pop_front();
}
void print(){
for(auto i:dq){
cout<<i<<" ";
}
}
void init(){
T tmp;
for(unsigned i=0;i<maxlen;i++){
cin>>tmp;
push(tmp);
}
}
};
单调栈
template <typename T>
class monotonicStackC{
private:
deque<T>st;
public:
monotonicStackC(int len=0){
st.clear();
}
void push(int a){
while(st.size()&&st.back()>a){
st.pop_back();
}
st.push_back(a);
}
void pop(){
st.pop_back();
}
void print(){
for(auto i:st){
cout<<i<<" ";
}
}
void init(){
string s;
T tmp;
cin>>s;
while(~sscanf(s.c_str(),"%d",&tmp)){
push(tmp);
}
}
};
树状数组
template<typename T>
struct binaryIndexedTree{
public:
vector<T> tree;
template <typename _T>
_T lowbit(_T x){
return -x&x;
}
binaryIndexedTree(int len=0,int *a=nullptr){
tree.resize(len);
while(len--){
tree[len]=*(a+len);
}
}
void update(int x,int d){
while(x<tree.size()){
tree[x]+=d;
x+=lowbit(x);
}
}
T sum(int x){
int ans=0;
while(x>0){
ans+=tree[x];
x-=lowbit(x);
}
return ans;
}
T sum(int l,int r){
return sum(r)-sum(l-1);
}
};
线段树
struct{
int l,r,sum=0,lazy=0;
}st[200005];
int get(int l,int r){
return (l+r-2)|(l!=r);
}
void build(int l,int r){
st[get(l,r)].l=l;
st[get(l,r)].r=r;
if(l!=r){
build(l,l+r>>1);
build((l+r>>1)+1,r);
st[get(l,r)].sum=st[get(l,l+r>>1)].sum+st[get((l+r>>1)+1,r)].sum;
}else{
st[get(l,r)].sum=a[l];
}
}
void pushdown(int l,int r){
st[get(l,l+r>>1)].sum+=st[get(l,r)].lazy*((l+r>>1)-l+1);
st[get((l+r>>1)+1,r)].sum+=st[get(l,r)].lazy*(r-(l+r>>1));
st[get(l,l+r>>1)].lazy+=st[get(l,r)].lazy;
st[get((l+r>>1)+1,r)].lazy+=st[get(l,r)].lazy;
st[get(l,r)].lazy=0;
}
void update(int l,int r,const int left,const int right,const int k){
if(l>=left&&r<=right){
st[get(l,r)].sum+=k*(r-l+1);
st[get(l,r)].lazy+=k;
}else{
if(st[get(l,r)].lazy&&l!=r){
pushdown(l,r);
}
if(left<=l+r>>1){
update(l,l+r>>1,left,right,k);
}
if(right>l+r>>1){
update((l+r>>1)+1,r,left,right,k);
}
st[get(l,r)].sum=st[get(l,l+r>>1)].sum+st[get((l+r>>1)+1,r)].sum;
}
}
int query(int l,int r,const int left,const int right){
if(l>=left&&r<=right){
return st[get(l,r)].sum;
}else{
if(st[get(l,r)].lazy&&l!=r){
pushdown(l,r);
}
int ans=0;
if(left<=l+r>>1){
ans+=query(l,l+r>>1,left,right);
}
if(right>l+r>>1){
ans+=query((l+r>>1)+1,r,left,right);
}
return ans;
}
}
二叉搜索树
template <typename T>
struct Node{
T data;
Node *left;
Node *right;
};
template <typename T>
class binarySearchTreeC{
private:
Node<T> *root;
Node<T> *insertNode(Node<T> *node,T data){
if(node==nullptr){
node=new Node<T>;
node->data=data;
node->left=nullptr;
node->right=nullptr;
}else if(data<node->data){
node->left=insertNode(node->left,data);
}else if(data>node->data){
node->right=insertNode(node->right,data);
}
return node;
}
Node<T> *findMinNode(Node<T> *node){
while(node->left!=nullptr){
node=node->left;
}
return node;
}
Node<T> *deleteNode(Node<T> *node,T data){
if(node==nullptr){
return node;
}else if(data<node->data){
node->left=deleteNode(node->left,data);
}else if(data>node->data){
node->right=deleteNode(node->right,data);
}else{
if(node->left==nullptr){
Node<T> *temp=node->right;
delete node;
return temp;
}else if(node->right==nullptr){
Node<T> *temp=node->left;
delete node;
return temp;
}
Node<T> *temp=findMinNode(node->right);
node->data=temp->data;
node->right=deleteNode(node->right,temp->data);
}
return node;
}
Node<T> *searchNode(Node<T> *node,T data){
if(node==nullptr||node->data==data){
return node;
}
if(node->data<data){
return searchNode(node->right,data);
}
return searchNode(node->left,data);
}
void preOrderTraversal(Node<T> *node){
if(node!=nullptr){
cout<<node->data<<" ";
preOrderTraversal(node->left);
preOrderTraversal(node->right);
}
}
void inOrderTraversal(Node<T> *node){
if(node!=nullptr){
InOrderTraversal(node->left);
cout<<node->data<<" ";
InOrderTraversal(node->right);
}
}
void postOrderTraversal(Node<T> *node){
if(node!=nullptr){
PostOrderTraversal(node->left);
PostOrderTraversal(node->right);
cout<<node->data<<" ";
}
}
public:
void BinarySearchTree(){ //建树
root=nullptr;
}
void insert(int data){ //插入
root=insertNode(root,data);
}
void remove(int data){ //删除
root=deleteNode(root,data);
}
void preorder(){ //先序遍历
preOrderTraversal(root);
}
void inorder(){ //中序遍历
inOrderTraversal(root);
}
void postorder(){ //后序遍历
postOrderTraversal(root);
}
Node<T> *search(T data){ //查找
return searchNode(root,data);
}
};
AVL
class AVLTree{
private:
struct Node{
int key,left,right,height;
Node():key(0),left(-1),right(-1),height(1){}
};
Node nodes[100];
int root,nodeCount;
int height(int nodeIndex){
if(nodeIndex==-1){
return 0;
}
return nodes[nodeIndex].height;
}
int balanceFactor(int nodeIndex){
if(nodeIndex==-1){
return 0;
}
return height(nodes[nodeIndex].left) - height(nodes[nodeIndex].right);
}
void updateHeight(int nodeIndex){
if(nodeIndex==-1){
return;
}
nodes[nodeIndex].height=1 + max(height(nodes[nodeIndex].left), height(nodes[nodeIndex].right));
}
int rotateRight(int y){
int x=nodes[y].left;
int T2=nodes[x].right;
nodes[x].right=y;
nodes[y].left=T2;
updateHeight(y);
updateHeight(x);
return x;
}
int rotateLeft(int x){
int y=nodes[x].right;
int T2=nodes[y].left;
nodes[y].left=x;
nodes[x].right=T2;
updateHeight(x);
updateHeight(y);
return y;
}
int balance(int nodeIndex){
int balance=balanceFactor(nodeIndex);
if (balance>1){
if (balanceFactor(nodes[nodeIndex].left)<0){
nodes[nodeIndex].left=rotateLeft(nodes[nodeIndex].left);
}
return rotateRight(nodeIndex);
}
if (balance<-1){
if (balanceFactor(nodes[nodeIndex].right)>0){
nodes[nodeIndex].right=rotateRight(nodes[nodeIndex].right);
}
return rotateLeft(nodeIndex);
}
return nodeIndex;
}
int findMin(int nodeIndex){
while (nodes[nodeIndex].left!=-1){
nodeIndex=nodes[nodeIndex].left;
}
return nodeIndex;
}
int deleteNode(int nodeIndex, int key){
if (nodeIndex==-1) return nodeIndex;
if (key<nodes[nodeIndex].key){
nodes[nodeIndex].left=deleteNode(nodes[nodeIndex].left, key);
}else if (key>nodes[nodeIndex].key){
nodes[nodeIndex].right=deleteNode(nodes[nodeIndex].right, key);
}else{
if (nodes[nodeIndex].left==-1){
int temp=nodes[nodeIndex].right;
nodes[nodeIndex]=nodes[temp];
return temp;
}else if (nodes[nodeIndex].right==-1){
int temp=nodes[nodeIndex].left;
nodes[nodeIndex]=nodes[temp];
return temp;
}else{
int temp=findMin(nodes[nodeIndex].right);
nodes[nodeIndex].key=nodes[temp].key;
nodes[nodeIndex].right=deleteNode(nodes[nodeIndex].right, nodes[temp].key);
}
}
updateHeight(nodeIndex);
return balance(nodeIndex);
}
public:
AVLTree():root(-1),nodeCount(0){}
void insert(int key){
root=insert(root,key);
}
int insert(int nodeIndex,int key){
if(nodeIndex==-1){
if(nodeCount>=100){
return -1;
}
nodes[nodeCount].key=key;
nodes[nodeCount].left=-1;
nodes[nodeCount].right=-1;
nodeCount++;
return nodeCount-1;
}
if(key<nodes[nodeIndex].key){
nodes[nodeIndex].left=insert(nodes[nodeIndex].left,key);
}else if(key>nodes[nodeIndex].key){
nodes[nodeIndex].right=insert(nodes[nodeIndex].right,key);
}else{
return nodeIndex;
}
updateHeight(nodeIndex);
return balance(nodeIndex);
}
void deleteKey(int key){
root=deleteNode(root,key);
}
void preOrder(int nodeIndex){
if(nodeIndex==-1){
return;
}
preOrder(nodes[nodeIndex].left);
cout<<nodes[nodeIndex].key<<' ';
preOrder(nodes[nodeIndex].right);
}
void preOrder(){
preOrder(root);
}
};
红黑树
enum Color{
RED,BLACK
};
class RedBlackTree{
private:
struct Node{
int key,left,right,parent;
Color color;
Node():key(0),left(-1),right(-1),parent(-1),color(BLACK){}
};
Node nodes[100];
int root,size;
void leftRotate(int x){
int y=nodes[x].right;
nodes[x].right=nodes[y].left;
if(nodes[y].left!=-1){
nodes[nodes[y].left].parent=x;
}
nodes[y].parent=nodes[x].parent;
if(nodes[x].parent==-1){
root=y;
}else if(x==nodes[nodes[x].parent].left){
nodes[nodes[x].parent].left=y;
}else{
nodes[nodes[x].parent].right=y;
}
nodes[y].left=x;
nodes[x].parent=y;
}
void rightRotate(int x){
int y=nodes[x].left;
nodes[x].left=nodes[y].right;
if(nodes[y].right!=-1){
nodes[nodes[y].right].parent=x;
}
nodes[y].parent=nodes[x].parent;
if(nodes[x].parent==-1){
root=y;
}else if(x==nodes[nodes[x].parent].right){
nodes[nodes[x].parent].right=y;
}else{
nodes[nodes[x].parent].left=y;
}
nodes[y].right=x;
nodes[x].parent=y;
}
void fixInsert(int k){
int u;
while(nodes[nodes[k].parent].color==RED){
if(nodes[k].parent==nodes[nodes[nodes[k].parent].parent].right){
u=nodes[nodes[nodes[k].parent].parent].left;
if(nodes[u].color==RED){
nodes[u].color=BLACK;
nodes[nodes[k].parent].color=BLACK;
nodes[nodes[nodes[k].parent].parent].color=RED;
k=nodes[nodes[k].parent].parent;
}else{
if(k==nodes[nodes[k].parent].left){
k=nodes[k].parent;
rightRotate(k);
}
nodes[nodes[k].parent].color=BLACK;
nodes[nodes[nodes[k].parent].parent].color=RED;
leftRotate(nodes[nodes[k].parent].parent);
}
}else{
u=nodes[nodes[nodes[k].parent].parent].right;
if(nodes[u].color==RED){
nodes[u].color=BLACK;
nodes[nodes[k].parent].color=BLACK;
nodes[nodes[nodes[k].parent].parent].color=RED;
k=nodes[nodes[k].parent].parent;
}else{
if(k==nodes[nodes[k].parent].right){
k=nodes[k].parent;
leftRotate(k);
}
nodes[nodes[k].parent].color=BLACK;
nodes[nodes[nodes[k].parent].parent].color=RED;
rightRotate(nodes[nodes[k].parent].parent);
}
}
if(k==root){
break;
}
}
nodes[root].color=BLACK;
}
void fixDelete(int x){
int s;
while(x!=root && nodes[x].color==BLACK){
if(x==nodes[nodes[x].parent].left){
s=nodes[nodes[x].parent].right;
if(nodes[s].color==RED){
nodes[s].color=BLACK;
nodes[nodes[x].parent].color=RED;
leftRotate(nodes[x].parent);
s=nodes[nodes[x].parent].right;
}
if(nodes[nodes[s].left].color==BLACK && nodes[nodes[s].right].color==BLACK){
nodes[s].color=RED;
x=nodes[x].parent;
}else{
if(nodes[nodes[s].right].color==BLACK){
nodes[nodes[s].left].color=BLACK;
nodes[s].color=RED;
rightRotate(s);
s=nodes[nodes[x].parent].right;
}
nodes[s].color=nodes[nodes[x].parent].color;
nodes[nodes[x].parent].color=BLACK;
nodes[nodes[s].right].color=BLACK;
leftRotate(nodes[x].parent);
x=root;
}
}else{
s=nodes[nodes[x].parent].left;
if(nodes[s].color==RED){
nodes[s].color=BLACK;
nodes[nodes[x].parent].color=RED;
rightRotate(nodes[x].parent);
s=nodes[nodes[x].parent].left;
}
if(nodes[nodes[s].right].color==BLACK && nodes[nodes[s].left].color==BLACK){
nodes[s].color=RED;
x=nodes[x].parent;
}else{
if(nodes[nodes[s].left].color==BLACK){
nodes[nodes[s].right].color=BLACK;
nodes[s].color=RED;
leftRotate(s);
s=nodes[nodes[x].parent].left;
}
nodes[s].color=nodes[nodes[x].parent].color;
nodes[nodes[x].parent].color=BLACK;
nodes[nodes[s].left].color=BLACK;
rightRotate(nodes[x].parent);
x=root;
}
}
}
nodes[x].color=BLACK;
}
void transplant(int u, int v){
if(nodes[u].parent==-1){
root=v;
}else if(u==nodes[nodes[u].parent].left){
nodes[nodes[u].parent].left=v;
}else{
nodes[nodes[u].parent].right=v;
}
nodes[v].parent=nodes[u].parent;
}
int minimum(int node){
while(nodes[node].left!=-1){
node=nodes[node].left;
}
return node;
}
public:
RedBlackTree(){
size=0;
root=-1;
}
void insert(int key){
if(size >= 100){
cout << "Tree is full" << endl;
return;
}
int node=size++;
nodes[node].key=key;
nodes[node].parent=-1;
nodes[node].left=-1;
nodes[node].right=-1;
nodes[node].color=RED;
int y=-1;
int x=root;
while(x!=-1){
y=x;
if(key<nodes[x].key){
x=nodes[x].left;
}else{
x=nodes[x].right;
}
}
nodes[node].parent=y;
if(y==-1){
root=node;
}else if(key<nodes[y].key){
nodes[y].left=node;
}else{
nodes[y].right=node;
}
if(nodes[node].parent==-1){
nodes[node].color=BLACK;
return;
}
if(nodes[nodes[node].parent].parent==-1){
return;
}
fixInsert(node);
}
void deleteNode(int key){
int node=root;
while(node!=-1 && nodes[node].key!=key){
if(key<nodes[node].key){
node=nodes[node].left;
}else{
node=nodes[node].right;
}
}
if(node==-1){
return;
}
int y=node;
int yOriginalColor=nodes[y].color;
int x;
if(nodes[y].left==-1){
x=nodes[y].right;
transplant(y, nodes[y].right);
}else if(nodes[y].right==-1){
x=nodes[y].left;
transplant(y, nodes[y].left);
}else{
y=minimum(nodes[y].right);
yOriginalColor=nodes[y].color;
x=nodes[y].right;
if(nodes[y].parent==node){
nodes[x].parent=y;
}else{
transplant(y, nodes[y].right);
nodes[y].right=nodes[node].right;
nodes[nodes[y].right].parent=y;
}
transplant(node, y);
nodes[y].left=nodes[node].left;
nodes[nodes[y].left].parent=y;
nodes[y].color=nodes[node].color;
}
if(yOriginalColor==BLACK){
fixDelete(x);
}
}
void inOrderHelper(int node){
if(node!=-1){
inOrderHelper(nodes[node].left);
cout<<nodes[node].key<<" ";
inOrderHelper(nodes[node].right);
}
}
void inOrder(){
inOrderHelper(root);
}
};
FHQ Treap
struct node{
int key,val,l,r,sz;
i64 sum;
}tr[1000005];
int root,cnt;
int newnode(int v){
++cnt;
tr[cnt].key=rand();
tr[cnt].val=v;
tr[cnt].l=tr[cnt].r=0;
tr[cnt].sz=1;
tr[cnt].sum=v;
return cnt;
}
void pushup(int x){
if(!x){
return;
}
int l=tr[x].l,r=tr[x].r;
tr[x].sz=tr[l].sz+tr[r].sz+1;
tr[x].sum=tr[l].sum+tr[r].sum+tr[x].val;
}
void pushdown(int x){
if(!x){
return;
}
}
_Pi splitbyval(int x,int v){
if(!x){
return{0,0};
}
pushdown(x);
if(tr[x].val<=v){
auto p=splitbyval(tr[x].r,v);
tr[x].r=p.first;
pushup(x);
return{x,p.second};
}else{
auto p=splitbyval(tr[x].l,v);
tr[x].l=p.second;
pushup(x);
return{p.first,x};
}
}
_Pi splitbysize(int x,int k){
if(!x){
return{0,0};
}
pushdown(x);
int lsz=tr[tr[x].l].sz;
if(lsz+1<=k){
auto p=splitbysize(tr[x].r,k-lsz-1);
tr[x].r=p.first;
pushup(x);
return{x,p.second};
}else{
auto p=splitbysize(tr[x].l,k);
tr[x].l=p.second;
pushup(x);
return{p.first,x};
}
}
int merge(int x,int y){
if(!x||!y){
return x+y;
}
pushdown(x);
pushdown(y);
if(tr[x].key>tr[y].key){
tr[x].r=merge(tr[x].r,y);
pushup(x);
return x;
}else{
tr[y].l=merge(x,tr[y].l);
pushup(y);
return y;
}
}
void insert(int v){
auto p=splitbyval(root,v);
root=merge(merge(p.first,newnode(v)),p.second);
}
void del(int v){
auto p1=splitbyval(root,v-1);
auto p2=splitbyval(p1.second,v);
if(p2.first){
p2.first=merge(tr[p2.first].l,tr[p2.first].r);
}
root=merge(p1.first,merge(p2.first,p2.second));
}
int getrank(int v){
auto p=splitbyval(root,v-1);
int res=tr[p.first].sz+1;
root=merge(p.first,p.second);
return res;
}
int getkth(int k){
auto p1=splitbysize(root,k-1);
auto p2=splitbysize(p1.second,1);
int res=tr[p2.first].val;
root=merge(p1.first,merge(p2.first,p2.second));
return res;
}
int getpre(int v){
auto p=splitbyval(root,v-1);
auto p2=splitbysize(p.first,tr[p.first].sz-1);
int res=tr[p2.second].val;
root=merge(merge(p2.first,p2.second),p.second);
return res;
}
int getnxt(int v){
auto p=splitbyval(root,v);
auto p2=splitbysize(p.second,1);
int res=tr[p2.first].val;
root=merge(p.first,merge(p2.first,p2.second));
return res;
}
倍增
LCA
vector<int>v[500005];
int fa[500005][25],cost[500005][25],dep[500005];
int n,m,a,b,s;
// dfs,用来为 lca 算法做准备。接受两个参数:dfs 起始节点和它的父亲节点。
void dfs(int root,int fno){
// 初始化:第 2^0=1 个祖先就是它的父亲节点,dep 也比父亲节点多 1。
fa[root][0]=fno;
dep[root]=dep[fno]+1;
// 初始化:其他的祖先节点:第 2^i 的祖先节点是第 2^(i-1) 的祖先节点的第
// 2^(i-1) 的祖先节点。
for(int i=1;i<=20;i++){
fa[root][i]=fa[fa[root][i-1]][i-1];
}
// 遍历子节点来进行 dfs。
int sz=v[root].size();
for(int i=0;i<sz;i++){
if(v[root][i]==fno){
continue;
}
dfs(v[root][i],root);
}
}
// lca。用倍增算法算取 x 和 y 的 lca 节点。
int lca(int x,int y){
// 令 y 比 x 深。
if(dep[x]>dep[y]){
swap(x,y);
}
// 令 y 和 x 在一个深度。
int tmp=dep[y]-dep[x];
for(int j=0;tmp;j++,tmp>>=1){
if(tmp&1){
y=fa[y][j];
}
}
// 如果这个时候 y=x,那么 x,y 就都是它们自己的祖先。
if(y==x){
return x;
}
// 不然的话,找到第一个不是它们祖先的两个点。
for(int j=20;j>=0&&y!=x;j--){
if(fa[x][j]!=fa[y][j]){
x=fa[x][j];
y=fa[y][j];
}
}
// 返回结果。
return fa[x][0];
}
ST表
int f[1005][20],a[1005],LOGN[1005],n,m,l,r;
void getlog(int k=2){
LOGN[0]=LOGN[1]=0;
for(int i=2;i<n+2;i++){
LOGN[i]=LOGN[i/k]+1;
}
}
void ST(int n){
for(int i=0;i<n;i++){
f[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;j++){
for(int i=0;i+(1<<j)<=n;i++){
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
int RMQ(int l,int r){
return max(f[l][LOGN[r-l+1]],f[r-(1<<LOGN[r-l+1])+1][LOGN[r-l+1]]);
}
图论
存图
#### 直接存图
```cpp
struct edge{
int from,to,w;
edge(int _from=0,int _to=0,int _w=0){
from=_from;
to=_to;
w=_w;
}
}graph0[M];
int cnt0;
void init0(){
for(int i=0;i<n;i++){
graph0[i]=edge{0,0,0};
}
}
void addedge0(int from,int to,int w=1){
graph0[cnt0++]=edge{from,to,w};
}
int findedge0(int from,int to){
for(int i=0;i<cnt0;i++){
if(graph0[i].from==from&&graph0[i].to==to){
return graph0[i].w;
}
}
return -1;
}
```
复杂度:
- 查询是否存在某条边:$O(m)$。
- 遍历一个点的所有出边:$O(m)$。
- 遍历整张图:$O(nm)$。
- 空间复杂度:$O(m)$。
应用:由于直接存边的遍历效率低下,一般不用于遍历图。在 Kruskal 算法中,由于需要将边按边权排序,需要直接存边。在有的题目中,需要多次建图(如建一遍原图,建一遍反图),此时既可以使用多个其它数据结构来同时存储多张图,也可以将边直接存下来,
需要重新建图时利用直接存下的边来建图。
#### 邻接矩阵
```cpp
int graph1[1005][1005];
void init1(int a=-1){
memset(graph1,a,sizeof graph1);
}
void addedge1(int from,int to,int w=1){
graph1[from][to]=w;
}
int findedge1(int from,int to){
return graph1[from][to];
}
```
复杂度:
- 查询是否存在某条边:$O(1)$。
- 遍历一个点的所有出边:$O(n)$。
- 遍历整张图:$O(n^2)$。
- 空间复杂度:$O(n^2)$。
应用:邻接矩阵只适用于没有重边(或重边可以忽略)的情况。其最显著的优点是可以 $O(1)$ 查询一条边是否存在。由于邻接矩阵在稀疏图上效率很低(尤其是在点数较多的图上,空间无法承受),所以一般只会在稠密图上使用邻接矩阵。
#### 邻接表
```
vector<pair<int,int>>graph2[1005];
void init2(){
for(int i=0;i<n;i++){
graph2[i].clear();
}
}
void addedge2(int from,int to,int w=1){
graph2[from].emplace_back(to,w);
}
int findedge2(int from,int to){
for(int i=0;i<int(graph2[from].size());i++){
if(graph2[from][i].first==to){
return graph2[from][i].second;
}
}
return -1;
}
```
复杂度:
- 查询是否存在 $u$ 到 $v$ 的边:$O(d^+(u))$(如果事先进行了排序就可以使用 二分查找 做到 $O(\log(d^+(u))))$。
- 遍历点 u 的所有出边:O(d^+(u))。
- 遍历整张图:O(n+m)。
- 空间复杂度:O(m)。
应用:存各种图都很适合,除非有特殊需求(如需要快速查询一条边是否存在,尤其适用于需要对一个点的所有出边进行排序的场合。
#### 链式前向星
```cpp
int head[1005],from[M],nxt[M],to[M],w[M],cnt; //from可省略
void init(){
memset(head,-1,sizeof head);
memset(from,-1,sizeof from);
memset(nxt,-1,sizeof nxt);
memset(to,-1,sizeof to);
cnt=0;
}
void addedge(int f,int t,int ww){
nxt[++cnt]=head[f];
head[f]=cnt;
to[cnt]=t;
w[cnt]=ww;
from[cnt]=f;
}
int findedge(int f,int t){
for(int i=f;~i;i=nxt[i]){
if(to[i]==t){
return w[i];
}
}
return -1;
}
```
复杂度:
- 查询是否存在 $u$ 到 $v$ 的边:$O(d^+(u))$。
- 遍历点 $u$ 的所有出边:$O(d^+(u))$。
- 遍历整张图:$O(n+m)$。
- 空间复杂度:$O(m)$。
应用:存各种图都很适合,但不能快速查询一条边是否存在,也不能方便地对一个点的出边进行排序。优点是边是带编号的,有时会非常有用,而且如果 `cnt` 的初始值为奇数,存双向边时 `i ^ 1` 即是 `i` 的反边(常用于 网络流)。
### 拓扑排序
```cpp
vector<int>topo;
bool toposort(){
for(int i=0;i<n;i++){
for(auto j:graph[i]){
in[j.first]++;
}
}
int u;
queue<int>q;
for(int i=0;i<n;i++){
if(in[i]==0){
q.push(i);
}
}
while(!q.empty()){
u=q.front();
q.pop();
topo.push_back(u);
for(auto i:graph[u]){
in[i.first]--;
if(in[i.first]==0){
q.push(i.first);
}
}
}
if(int(topo.size())==n){
return 1;
}
return 0;
}
```
### Bellman-Ford
```cpp
int dis[1005],from,v,w;
bool Bellman_Ford(int s){
memset(dis,0x3f,sizeof dis);
dis[s]=0;
bool flag; //判负环(从s能达到的)
for(int i=0;i<n;i++){
flag=0;
for(int j=0;j<cnt;j++){
if(dis[from]==0x3f3f3f3f){
continue;
}
//无穷大与常数加减仍然为无穷大
//因此最短路长度为0x3f3f3f3f的点引出的边不可能发生松弛操作
if(dis[edge[j].to]>dis[edge[j].from]+edge[j].w){
dis[edge[j].to]=dis[edge[j].from]+edge[j].w;
flag=1;
}
}
//没有可以松弛的边时就停止算法
if(!flag){
break;
}
}
//第n轮循环仍然可以松弛时说明s点可以抵达一个负环
return flag;
}
```
### SPFA
```cpp
int dis[1005],cnt[1005],vis[1005];
queue<int>q;
bool SPFA(int s){ //返回是否存在负环
memset(dis,0x3f,sizeof dis);
memset(cnt,0,sizeof cnt);
memset(vis,0,sizeof vis);
dis[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty()){
vis[q.front()]=0;
for(auto i:edge[q.front()]){
if(dis[i.first]>dis[q.front()]+i.second){
dis[i.first]=dis[q.front()]+i.second;
cnt[i.first]=cnt[q.front()]+1;//记录最短路经过的边数
if(cnt[i.first]>=n){
return 1;
}
//在不经过负环的情况下,最短路至多经过n-1条边
//因此如果经过了多于n条边,一定说明经过了负环
if(!vis[i.first]){
q.push(i.first);
vis[i.first]=1;
}
}
}
q.pop();
}
return 0;
}
```
### Dijkstra(暴力)
```cpp
void notUseHeapDijkstra(int s){
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
dis[s]=0;
int u,mind,v,w;
for(int i=0;i<n;i++){
u=0;
mind=0x3f3f3f3f;
for(int j=1;j<=n;j++){
if(!vis[j]&&dis[j]<mind){
u=j;
mind=dis[j];
}
}
vis[u]=1;
for(auto i:e[u]){
if(dis[i.first]>dis[u]+i.second){
dis[i.first]=dis[u]+i.second;
}
}
}
}
```
### Dijkstra(堆)
```cpp
struct node{
int dis,u;
bool operator<(const node &a)const{
return this->dis>a.dis;
}
};
priority_queue<node>q;
void useHeapDijkstra(int s){
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
int u,v,w;
dis[s]=0;
q.push({0,s});
while(q.size()){
u=q.top().u;
q.pop();
if(vis[u]){
continue;
}
vis[u]=1;
for(auto i:e[u]){
if(dis[v]>dis[u]+w){
if(dis[i.first]>dis[u]+i.second){
dis[i.first]=dis[u]+i.second;
q.push({dis[i.first],i.first});
}
}
}
}
}
```
### Floyd_Warshall
```cpp
int f[1005][1005];
bool Floyd(){ //返回有没有负环
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
}
}
//判负环
for(int i=0;i<n;i++){
if(f[i][i]<0){
return 1;
}
}
return 0;
}
```
### Kruskal
```cpp
int findroot(int x){
return fa[x]==x?x:fa[x]=findroot(fa[x]);
}
void merge(int x,int y){
x=findroot(x);
y=findroot(y);
fa[x]=y;
}
bool cmp(Edge A,Edge B){
return A.w<B.w;
}
int Kruskal(){
sort(edge,edge+cntedge,cmp);
int tot=0,ans=0,xr,yr;
for(int i=0;i<cntedge;i++){
xr=findroot(edge[i].u);
yr=findroot(edge[i].v);
if(xr!=yr){
Merge(xr,yr);
tot++;
ans+=edge[i].w;
}
if(tot>=b){
return ans;
}
}
return -1;//图不连通
}
```
### Prim(暴力)
```cpp
void notUseHeapPrim(int s){
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
dis[s]=0;
int u,mind,v,w;
for(int i=0;i<n;i++){
u=0;
mind=0x3f3f3f3f;
for(int j=1;j<=n;j++){
if(!vis[j]&&dis[j]<mind){
u=j;
mind=dis[j];
}
}
vis[u]=1;
for(auto i:e[u]){
if(dis[i.first]>i.second){
dis[i.first]=i.second;
}
}
}
}
```
### Prim(堆)
```cpp
struct cmp{
bool operator () (_Pi a,_Pi b){
return a.first>b.first;
}
};
_SPQ(_Pi,cmp) q;
bool useHeapPrim(){
int cnt=0;
_Pi t;
assmax_s(d);
d[1]=0;
q.push({0,1});
while(q.size()){
if(cnt==n){
break;
}
t=q.top();
q.pop();
if(inmst[t.second]){
continue;
}
inmst[t.second]=1;
cnt++;
sum+=t.first;
for(auto i:e[t.second]){
if(!inmst[i.first]&&i.second<d[i.first]){
d[i.first]=i.second;
q.push({i.second,i.first});
}
}
}
return cnt!=n;
}
```
### 匈牙利算法
```cpp
bool find(int x){
for(auto i:e[x]){
if(vis[i]){
continue;
}
vis[i]=1;
if(a[i]==-1||find(a[i])){
a[i]=x;
return 1;
}
}
return 0;
}
int hungary(){
int ans=0;
assneg(a);
for(int i=1;i<=n;i++){
clr(vis);
if(find(i)){
ans++;
}
}
return ans;
}
```
### Edmonds–Karp
```cpp
void add_edge(int u,int v,int w){
e[cnt]={v,head[u],w};
head[u]=cnt++;
e[cnt]={u,head[v],0};
head[v]=cnt++;
} //奇偶存图
int Edmonds_Karp(int s,int t){
int mflow=0;
while(1){
clr(flow);
flow[s]=0x3f3f3f3f3f3f3f3f;
q.push(s);
while(q.size()){
for(int i=head[q.front()];~i;i=e[i].next){
v=e[i].to;
if(!flow[v]&&e[i].cap>0){
pre[v]=i;
flow[v]=min(flow[q.front()],(int)e[i].cap);
q.push(v);
}
}
q.pop();
}
if(!flow[t]){
break;
}
for(int i=t;i!=s;i=e[pre[i]^1].to){
e[pre[i]].cap-=flow[t];
e[pre[i]^1].cap+=flow[t];
}
mflow+=flow[t];
}
return mflow;
}
```
### Dinic
```cpp
void add_edge(int u,int v,int w){
e[idx]={v,head[u],w};
head[u]=idx++;
e[idx]={u,head[v],0};
head[v]=idx++;
}
bool bfs(int s,int t){
assneg(level);
queue<int>q;
level[s]=0;
q.push(s);
while(q.size()){
for(int i=head[q.front()];~i;i=e[i].next){
v=e[i].to;
if(level[v]<0&&e[i].cap>0){
level[v]=level[q.front()]+1;
q.push(v);
if(v==t){
return 1;
}
}
}
q.pop();
}
return 0;
}
int dfs(int u,int t,int min_flow){
if(u==t){
return min_flow;
}
for(int &i=cur[u];~i;i=e[i].next){
v=e[i].to;
if(level[v]==level[u]+1&&e[i].cap>0){
w=dfs(v,t,min(min_flow,e[i].cap));
if(w>0){
e[i].cap-=w;
e[i^1].cap+=w;
return w;
}
}
}
return 0;
}
int dinic(int s,int t){
int max_flow=0;
while(bfs(s,t)){
memcpy(cur,head,sizeof cur);
while((w=dfs(s,t,INF))>0){
max_flow+=w;
}
}
return max_flow;
}
```
### ISAP
```cpp
struct Edge{
int to,next,cap;
}e[20005];
int head[205],cnt,pre[205],gap[205],d[205],cur[205];
int n,m,s,t,u,v,w;
void add_edge(int u,int v,int w){
e[cnt]={v,head[u],w};
head[u]=cnt++;
e[cnt]={u,head[v],0};
head[v]=cnt++;
}
void bfs(){
assneg(d);
clr(gap);
queue<int> q;
q.push(t);
d[t]=0;
gap[0]=1;
while(q.size()){
for(int i=head[q.front()];~i;i=e[i].next){
int v=e[i].to;
if(d[v]==-1){
d[v]=d[q.front()]+1;
gap[d[v]]++;
q.push(v);
}
}
q.pop();
}
}
int ISAP(int s,int t){
bfs();
memcpy(cur,head,sizeof(head));
u=s;
int flow=0,i,f,neck;
while(d[s]<n){
if(u==t){
f=0x3f3f3f3f3f3f3f3f;
for(int i=s;i!=t;i=e[cur[i]].to){
if(f>e[cur[i]].cap){
f=e[cur[i]].cap;
neck=i;
}
}
for(int i=s;i!=t;i=e[cur[i]].to){
e[cur[i]].cap-=f;
e[cur[i]^1].cap+=f;
}
flow+=f;
u=neck;
}
for(i=cur[u];~i;i=e[i].next){
if(e[i].cap>0&&d[u]==d[e[i].to]+1){
break;
}
}
if(~i){
cur[u]=i;
pre[e[i].to]=u;
u=e[i].to;
}else{
if(--gap[d[u]]==0){
break;
}
int mind=n;
for(int i=head[u];~i;i=e[i].next){
if(e[i].cap>0&&mind>d[e[i].to]){
mind=d[e[i].to];
cur[u]=i;
}
}
d[u]=mind+1;
gap[d[u]]++;
if(u!=s){
u=pre[u];
}
}
}
return flow;
}
```
### tarjan
#### 强连通分量
```cpp
void tarjan(int u){
low[u]=dfn[u]=++dfnc;
st.push(u);
inst[u]=1;
_FE(i,e[u]){
if(!dfn[i]){
tarjan(i);
low[u]=min(low[u],low[i]);
}else if(inst[u]){
low[u]=min(low[u],dfn[i]);
}
}
if(dfn[u]==low[u]){
sccc++;
while(st.top()!=u){
scc[st.top()]=sccc;
sz[sccc]++;
inst[st.top()]]=0;
st.pop();
}
}
}
```
#### 割点(割顶)
```cpp
void tarjan(int u,int fa){
low[u]=dfn[u]=++cnt;
int ch=0;
_FE(i,e[u]){
if(!dfn[i]){
ch++;
tarjan(i,u);
low[u]=min(low[u],low[i]);
if(fa!=u&&low[i]>=dfn[u]&&!f[u]){
f[u]=1;
ans++;
}
}else if(i!=fa){
low[u]=min(low[u],dfn[i]);
}
}
if(fa==u&&ch>=2&&!f[u]){
f[u]=1;
ans++;
}
}
```
#### 割边(桥)
```cpp
void tarjan(int u,int fa){
bool fl=0;
fat[u]=fa;
low[u]=dfn[u]=++cnt;
_FE(i,e[u]){
if(!dfn[i]){
tarjan(i,u);
low[u]=min(low[u],low[i]);
if(low[i]>dfn[u]){
f[i]=1;
ans++;
}
}else{
if(i!=fa||fl){
low[u]=min(low[u],dfn[i]);
}else{
fl=1;
}
}
}
}
```
#### 点双连通分量
```cpp
void tarjan(int u,int las){
low[u]=dfn[u]=++cnt;
st.push(u);
_FE(i,e[u]){
if(i.second==(las^1)){
continue;
}
if(!dfn[i.first]){
tarjan(i.first,i.second);
low[u]=min(low[u],low[i.first]);
}else{
low[u]=min(low[u],dfn[i.first]);
}
}
if(dfn[u]==low[u]){
ans.emplace_back(1,u);
while(st.top()!=u){
ans.back().push_back(st.top());
st.pop();
}
st.pop();
}
}
```
### 树的直径
```cpp
void dfs(int u,int fa){
s[u]=1;
f[u]=0;
_FE(i,e[u]){
if(i!=fa){
dfs(i,u);
s[u]+=s[i];
f[u]=max(f[u],s[i]);
}
}
f[u]=max(f[u],n-s[u]);
}
//f数组最小值的下标是树的重心
```
## 数论
### Miller-Rabin
```cpp
constexpr int p[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
ll mul(ll x,ll y,ll m){
return __int128(x)*y%m;
}
int fastpow(ll a,ll b,ll m){
if(!a){
return 0;
}
if(a==1||!b){
return 1;
}
a%=m;
ll ans=1;
while(b){
if(b&1){
ans=mul(ans,a,m);
}
a=mul(a,a,m);
b>>=1;
}
return ans;
}
bool miller_rabin(ll x){
if(x<=2){
return x==2;
}
if(!(x&1)){
return 0;
}
ll s=x-1,t=__builtin_ctzll(s),r;
s>>=t;
for(int i=0;i<25&&p[i]<x;i++){
if(!(x%p[i])){
return 0;
}
r=fastpow(p[i],s,x);
if(r==1||r==x-1||r==0){
continue;
}
for(int j=1;j<=t;j++){
r=mul(r,r,x);
if(r==x-1&&j!=t){
r=1;
break;
}
if(r==1){
return 0;
}
}
if(r!=1){
return 0;
}
}
return 1;
}
```
### exgcd
#### 正常版
```cpp
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){
x=1;
y=0;
return a;
}
ll gcd=exgcd(b,a%b,y,x);
y-=a/b*x;
return gcd;
}
```
#### 逆天码风迭代版
```cpp
int exgcd(int a,int b,int &x,int &y){
int x0=1,x1=0,x2=0,x3=1,c;
while(b){
c=a/b;
tie(x0,x1,x2,x3,a,b)=make_tuple(x2,x3,x0-x2*c,x1-x3*c,b,a-b*c);
}
x=x0;
y=x1;
return a;
}
```
#### 求逆元
```cpp
int inv(int a,int m){
int x,y,g=exgcd(a,m,x,y);
if(~g){
return (x%m+m)%m;
}else{
return -1;
}
}
```
### CRT
```cpp
ll crt(){
for(int i=0;i<n;i++){
m*=b[i];
}
for(int i=0;i<n;i++){
res=m/b[i];
exgcd(res,b[i],t,y);
t%=b[i];
ans=(ans+a[i]*res*t)%m;
}
return (ans+m)%m;
}
```
### exCRT
```cpp
ll mul(ll a,ll b,ll mod){
return __int128(a)*b%mod;
}
ll excrt(){
ans=a[0];
m=b[0];
for(int i=1;i<n;i++){
res=((a[i]-ans)%b[i]+b[i])%b[i];
gcd=exgcd(m,b[i],t,y);
t=mul(t,res/gcd,b[i]);
ans+=t*m;
m=b[i]/gcd*m;
ans=(ans%m+m)%m;
}
return ans;
}
```
### FFT
#### 无优化
```cpp
void dft(complex<double> *a,int len,int type){
if(len==1){
return;
}
complex<double> *f0=a,*f1=a+len/2;
for(int i=0;i<len;i++){
sav[i]=a[i];
}
for(int i=0;i<(len>>1);i++){
f0[i]=sav[i<<1];
f1[i]=sav[i<<1|1];
}
dft(f0,len>>1,type);
dft(f1,len>>1,type);
complex<double> tg(cos(2*pi/len),type*sin(2*pi/len)),buf(1.L,0.L);
for(int i=0;i<(len>>1);i++){
sav[i]=f0[i]+buf*f1[i];
sav[i+(len>>1)]=f0[i]-buf*f1[i];
buf*=tg;
}
for(int i=0;i<len;i++){
a[i]=sav[i];
}
}
void work(){
for(;lim<=n+m;lim<<=1);
dft(f,lim,1);
dft(g,lim,1);
for(int i=0;i<=lim;i++){
f[i]*=g[i];
}
dft(f,lim,-1);
for(int i=0;i<=lim;i++){
ans[i]+=int(f[i].real()/lim+.5);
}
}
```
#### 迭代
```cpp
void fft(complex<double>* f,int len,int type){
for(int i=0;i<len;i++){
if(i<r[i]){
swap(f[i],f[r[i]]);
}
}
complex<double> wn,w,x,y;
for(int i=1;i<len;i<<=1){
wn={cos(pi/i),type*sin(pi/i)};
for(int l=i<<1,j=0;j<len;j+=l){
w={1,0};
for(int k=0;k<i;k++,w*=wn){
x=f[j+k];
y=w*f[j+i+k];
f[j+k]=x+y;
f[j+i+k]=x-y;
}
}
}
}
void work(){
for(;lim<=n+m;lim<<=1,l++);
for(int i=0;i<=lim;i++){
r[i]=r[i>>1]>>1|(i&1)<<l-1;
}
fft(f,lim,1);
fft(g,lim,1);
for(int i=0;i<=lim;i++){
f[i]*=g[i];
}
fft(f,lim,-1);
for(int i=0;i<=lim;i++){
ans[i]+=int(f[i].real()/lim+.5);
}
}
```
#### 三步变两步
```cpp
void fft(complex<double>* f,int len,int type){
for(int i=0;i<len;i++){
if(i<r[i]){
swap(f[i],f[r[i]]);
}
}
complex<double> wn,w,x,y;
for(int i=1;i<len;i<<=1){
wn={cos(pi/i),type*sin(pi/i)};
for(int l=i<<1,j=0;j<len;j+=l){
w={1,0};
for(int k=0;k<i;k++,w*=wn){
x=f[j+k];
y=w*f[j+i+k];
f[j+k]=x+y;
f[j+i+k]=x-y;
}
}
}
if(~type){
return;
}
for(int i=0;i<len;i++){
f[i]/=len;
}
}
void work(){
for(;lim<=n+m;lim<<=1,l++);
for(int i=0;i<=lim;i++){
r[i]=r[i>>1]>>1|(i&1)<<l-1;
}
fft(f,lim,1);
for(int i=0;i<=lim;i++){
f[i]*=f[i];
}
fft(f,lim,-1);
for(int i=0;i<=lim;i++){
ans[i]+=int(f[i].imag()/2+.5);
}
}
```
### NTT
```cpp
constexpr ll pri=332748118,pr=3,mod=998244353;
void ntt(ll* f,int len,int type){
for(int i=0;i<len;i++){
if(i<r[i]){
swap(f[i],f[r[i]]);
}
}
for(int i=1;i<len;i<<=1){
ll wn=fpow(type==1?pr:pri,(mod-1)/(i<<1),mod);
for(int l=i<<1,j=0;j<len;j+=l){
ll w=1;
for(int k=0;k<i;k++,w=w*wn%mod){
ll x=f[j+k],y=w*f[j+k+i]%mod;
f[j+k]=(x+y)%mod;
f[i+j+k]=(x-y+mod)%mod;
}
}
}
}
void work(){
for(;lim<=n+m;lim<<=1,l++);
for(int i=0;i<=lim;i++){
r[i]=r[i>>1]>>1|(i&1)<<l-1;
}
ntt(f,lim,1);
ntt(g,lim,1);
for(int i=0;i<=lim;i++){
f[i]*=g[i];
}
ntt(f,lim,-1);
inv=fpow(lim,mod-2,mod);
for(int i=0;i<=lim;i++){
ans[i]+=f[i]*inv%mod;
}
}
```
### 高斯消元
```cpp
void gauss(){
_FF(k,0,n){
maxi=l;
_FF(i,maxi+1,n){
if(abs(a[i][k])>abs(a[maxi][k])){
maxi=i;
}
}
if(abs(a[maxi][k])<1e-8){
continue;
}
_FF(i,0,n+1){
swap(a[l][i],a[maxi][i]);
}
_FF(i,0,n){
if(i==l){
continue;
}
res=a[i][k]/a[l][k];
_FF(j,k,n+1){
a[i][j]-=a[l][j]*res;
}
}
l++;
}
if(l<n){
cout<<"No Solution";
}else{
cout<<_SP(2);
_FF(i,0,n){
cout<<a[i][n]/a[i][i]<<'\n';
}
}
}
```
## 树剖
```cpp
void dfs1(int r){
son[r]=-1;
sz[r]=1;
for(auto i:e[r]){
if(!d[i]){
d[i]=d[r]+1;
fa[i]=r;
dfs1(i);
sz[r]+=sz[i];
if(son[r]==-1||sz[i]>sz[son[r]]){
son[r]=i;
}
}
}
}
void dfs2(int r,int t){
top[r]=t;
cnt++;
dfn[r]=cnt;
rnk[cnt]=r;
if(~son[r]){
dfs2(son[r],t);
for(auto i:e[r]){
if(i!=son[r]&&i!=fa[r]){
dfs2(i,i);
}
}
}
}
```
## 快读快写
```cpp
//类似于文件读入,要用Ctrl+Z或F6结束读入,再一起输出(方便调试)
//快读
namespace Fast_I{
char *_Buf,*_Start_ptr,*_End_ptr;
streambuf *inbuf;
unsigned int Size;
bool _Ok;
struct Fast_Istream{
operator bool(){
return _Ok;
}
Fast_Istream(streambuf *in,unsigned int Sz){
_Ok=1;
Fast_I::Size=Sz;
inbuf=in;
_Start_ptr=_End_ptr=_Buf=new char[Sz];
}
Fast_Istream(const char *in,unsigned int Sz){
_Ok=1;
Fast_I::Size=Sz;
rdbuf(in);
_Start_ptr=_End_ptr=_Buf=new char[Sz];
}
Fast_Istream(unsigned int Sz){
_Ok=1;
Fast_I::Size=Sz;
_Start_ptr=_End_ptr=_Buf=new char[Sz];
}
void rdbuf(const char *File){
static ifstream __In__(File);
rdbuf(__In__.rdbuf());
}
void Get_Char(char &_Val){
if(_Start_ptr==_End_ptr){
_Start_ptr=_Buf;
_End_ptr=_Buf+inbuf->sgetn(_Buf,Size);
}
if(_Start_ptr==_End_ptr){
_Val=-1;
_Ok=0;
}else{
_Val=*_Start_ptr++;
}
}
Fast_Istream &operator>>(char &_Val){
if(_Ok){
Get_Char(_Val);
while(_Val==32||_Val==10||_Val==13||_Val==8||_Val==9||_Val==7||_Val==12||_Val==11){
Get_Char(_Val);
}
}
return *this;
}
Fast_Istream &operator>>(char *_Val){
if(_Ok){
Get_Char(*_Val);
while(*_Val==32||*_Val==10||*_Val==13||*_Val==8||*_Val==9||*_Val==7||*_Val==12||*_Val==11){
Get_Char(*_Val);
}
while(*_Val!=32&&*_Val!=10&&*_Val&&*_Val!=-1&&*_Val!=9 &&*_Val!=11&&*_Val!=12&&~*_Val){
Get_Char(*++_Val);
}
*_Val=0;
--_Start_ptr;
}
return *this;
}
Fast_Istream &operator>>(string &_Val){
if(_Ok){
char c;
Get_Char(c);
while(c==32||c==10||c==13||c==8||c==9||c==7||c==12||c==11){
Get_Char(c);
}
for(_Val.clear();c!=32&&c!=10&&c&&c!=-1&&c!=9&&c!=11&&c!=12&&~c;Get_Char(c)){
_Val.push_back(c);
}
--_Start_ptr;
}
return *this;
}
template <typename Typex>
void Get_Int(Typex &_Val){
if(_Ok){
char ch;
bool _F=0;
for(Get_Char(ch);(ch<48||ch>57)&&~ch;Get_Char(ch)){
_F=ch==45;
}
for(_Val=0;ch>47&&ch<58&&~ch;Get_Char(ch)){
_Val=_Val*10+(ch^48);
}
if(_F){
_Val=~_Val+1;
}
--_Start_ptr;
}
}
template <typename Typex>
void Get_Unsigned(Typex &_Val){
if(_Ok){
char ch;
Get_Char(ch);
while((ch<48||ch>57)&&~ch){
Get_Char(ch);
}
for(_Val=0;ch>47&&ch<58&&~ch;Get_Char(ch)){
_Val=_Val*10+(ch^48);
}
--_Start_ptr;
}
}
template <typename Typex>
void Get_Double(Typex &_Val){
if(_Ok){
char ch;
bool _F=0;
for(Get_Char(ch);(ch<48||ch>57)&&~ch;Get_Char(ch)){
_F=ch==45;
}
for(_Val=0;ch>47&&ch<58&&~ch;Get_Char(ch)){
_Val=_Val*10+(ch^48);
}
if(ch==46){
unsigned long long _Pow=1;
for(Get_Char(ch);ch>47&&ch<58&&~ch;Get_Char(ch)){
_Val+=Typex((ch^48)*1.0/(_Pow*=10));
}
}
if(_F){
_Val=-_Val;
}
--_Start_ptr;
}
}
Fast_Istream &operator>>(bool &_Val){
if(_Ok){
char ch;
Get_Char(ch);
while(ch==32||ch==10||ch==13||ch==8||ch==9||ch==7||ch==12||ch==11){
Get_Char(ch);
}
while(ch!=32&&ch!=10&&ch&&~ch&&ch!=9&&ch!=11&&ch!=12&&~ch){
_Val|=ch!=48;
Get_Char(ch);
}
--_Start_ptr;
}
return *this;
}
Fast_Istream &operator>>(short &_Val){
Get_Int(_Val);
return *this;
}
Fast_Istream &operator>>(int &_Val){
Get_Int(_Val);
return *this;
}
Fast_Istream &operator>>(long &_Val){
Get_Int(_Val);
return *this;
}
Fast_Istream &operator>>(long long &_Val){
Get_Int(_Val);
return *this;
}
Fast_Istream &operator>>(unsigned short &_Val){
Get_Unsigned(_Val);
return *this;
}
Fast_Istream &operator>>(unsigned int &_Val){
Get_Unsigned(_Val);
return *this;
}
Fast_Istream &operator>>(unsigned long &_Val){
Get_Unsigned(_Val);
return *this;
}
Fast_Istream &operator>>(unsigned long long &_Val){
Get_Unsigned(_Val);
return *this;
}
Fast_Istream &operator>>(float &_Val){
Get_Double(_Val);
return *this;
}
Fast_Istream &operator>>(double &_Val){
Get_Double(_Val);
return *this;
}
Fast_Istream &operator>>(long double &_Val){
Get_Double(_Val);
return *this;
}
template <typename Typex,typename... More>
void operator()(Typex &_Val,More &... _More){
*this>>_Val;
operator()(_More...);
}
void pop(){
char ch;
Get_Char(ch);
}
char peek(){
if(_Start_ptr==_End_ptr){
_Start_ptr=_Buf;
_End_ptr=_Buf+inbuf->sgetn(_Buf,Size);
}
if(_Start_ptr==_End_ptr){
_Ok=0;
return -1;
}else{
return *_Start_ptr;
}
}
template <typename Typex>
void operator()(Typex &_Val){
*this>>_Val;
}
template <typename Typex,typename...More>
streambuf *rdbuf(){
return inbuf;
}
void rdbuf(streambuf *_inbuf){
inbuf=_inbuf;
}
Fast_Istream getline(string &s,char _End='\n'){
if(_Ok){
char c;
Get_Char(c);
while((c==32||c==10||c==13||c==8||c==9||c==7||c==12||c==11||c==-1)&&c!=_End){
Get_Char(c);
}
for(s.clear();c!=_End&&~c;Get_Char(c)){
s.push_back(c);
}
--_Start_ptr;
}
return *this;
}
};
}// namespace Fast_I
//快写
namespace Fast_O{
string buf;
streambuf *outbuf;
int _M_precision=6;
struct Fast_Ostream{
Fast_Ostream(streambuf *out,unsigned int Size){
buf.reserve(Size);
outbuf=out;
}
Fast_Ostream(std::streambuf* out){
outbuf=out;
}
Fast_Ostream(const char *File,unsigned int Size){
buf.reserve(Size);
rdbuf(File);
}
void rdbuf(const char *File){
static ofstream __Out__(File);
rdbuf(__Out__.rdbuf());
}
Fast_Ostream(unsigned int Size){
buf.reserve(Size);
}
void flush(){
outbuf->sputn(buf.data(),buf.size());
buf.clear();
}
~Fast_Ostream(){
flush();
}
void endl(){
buf.push_back('\n');
}
Fast_Ostream &operator<<(char _Val){
buf.push_back(_Val);
return *this;
}
Fast_Ostream &operator<<(const char *_Val){
while(*_Val){
buf.push_back(*_Val++);
}
return *this;
}
Fast_Ostream &operator<<(const string &_Val){
buf+=_Val;
return *this;
}
template <typename Typex>
void Put_Unsigned(Typex _Val){
char *_Stack=(char *)malloc(sizeof(Typex)*3);
unsigned S_top=0;
while(_Val){
_Stack[++S_top]=(_Val%10)^48;
_Val/=10;
}
if(!S_top){
buf.push_back('0');
}
while(S_top){
buf.push_back(_Stack[S_top--]);
}
free(_Stack);
}
template <typename Typex>
void Put_Int(Typex _Val){
if(_Val<0){
buf.push_back('-');
Put_Unsigned(~_Val+1);
}else{
Put_Unsigned(_Val);
}
}
Fast_Ostream &operator<<(bool _Val){
buf.push_back(_Val?'1':'0');
return *this;
}
Fast_Ostream &operator<<(short _Val){
Put_Int(_Val);
return *this;
}
Fast_Ostream &operator<<(int _Val){
Put_Int(_Val);
return *this;
}
Fast_Ostream &operator<<(long _Val){
Put_Int(_Val);
return *this;
}
Fast_Ostream &operator<<(long long _Val){
Put_Int(_Val);
return *this;
}
Fast_Ostream &operator<<(unsigned short _Val){
Put_Unsigned(_Val);
return *this;
}
Fast_Ostream &operator<<(unsigned int _Val){
Put_Unsigned(_Val);
return *this;
}
Fast_Ostream &operator<<(unsigned long _Val){
Put_Unsigned(_Val);
return *this;
}
Fast_Ostream &operator<<(unsigned long long _Val){
Put_Unsigned(_Val);
return *this;
}
template <typename Typex>
void endl(const Typex &_Val){
*this<<_Val<<'\n';
}
template <typename Typex,typename... More>
void endl(const Typex &_Val,const More &... _More){
*this<<_Val;
endl(_More...);
}
template <typename Typex>
void operator()(const Typex &_Val){
*this<<_Val;
}
template <typename Typex,typename... More>
void operator()(const Typex &_Val,const More &... _More){
*this<<_Val;
operator()(_More...);
}
std::streambuf *rdbuf(){
return outbuf;
}
void rdbuf(std::streambuf *_outbuf){
outbuf=_outbuf;
}
};
}// namespace Fast_O
namespace Fast_IO{
Fast_I::Fast_Istream fin(cin.rdbuf(),16777216);
Fast_O::Fast_Ostream fout(cout.rdbuf());
}// namespace Fast_IO
#define fin Fast_IO::fin
#define fout Fast_IO::fout
#undef __CLOSE_SYNC
```
## 字符串算法
### 字符串Hash
```cpp
class stringHashC{
private:
constexpr static ull CRCTable[256]={
0ull,4340195606025211873ull,8680391212050423746ull,4921740848265695267ull,8434151890932224675ull,5275782923988786498ull,971319173584276833ull,3549304129150796416ull,
8068624508425914465ull,6035663343856174976ull,1697701945215342499ull,3149153052470335554ull,1942638347168553666ull,2796413900140090659ull,7098608258301592832ull,6825251901632711393ull,
6490467356436725221ull,7361623168864612868ull,2478163407092441639ull,2188552149708172742ull,3395403890430684998ull,1379681698106679463ull,6298306104940671108ull,7733644698202521445ull,
3885276694337107332ull,707133831123647077ull,5592827800280181318ull,8189461293375759783ull,4676819871590606631ull,8997099194556442822ull,4076205395479460069ull,336344856501516036ull,
3586070983360878317ull,1008578063553239308ull,5310510724793993519ull,8469513564492105422ull,4956326814184883278ull,8715327376724315055ull,4377104299416345484ull,37684403149984877ull,
6790807780861369996ull,7063530264788160877ull,2759363396213358926ull,1905095807503912623ull,3112528061657451567ull,1660301244664579022ull,6000793714265887725ull,8033404680093506572ull,
7770553388674214664ull,6335990505171215593ull,1414267662247294154ull,3430340053326002987ull,2223279952962664875ull,2513525083101607498ull,7398390024517330537ull,6527726247848323464ull,
301475225199879017ull,4040985565435702408ull,8960474201025592491ull,4639419168321876810ull,8152410790958920138ull,5555285262125432363ull,672689713003032072ull,3850198703474401769ull,
7172141966721756634ull,6896112701329056315ull,2017156127106478616ull,2865723297506999801ull,1622616839109181305ull,3080402236861542552ull,7994523456615702715ull,5965361108763242330ull,
896517745840219579ull,3479711083407338074ull,8360901865484057209ull,5205205806761112984ull,8754208598832690968ull,4991759417827375353ull,75368806299969754ull,4409230121257379643ull,
4150723131326255167ull,405654209777295326ull,4750353553099509757ull,9067959967341527068ull,5518726792426717852ull,8119159102239575421ull,3810191615007825246ull,638383042291733183ull,
6225056123314903134ull,7663067624797247423ull,3320602489329158044ull,1310088679005751421ull,2553532169166932733ull,2257586620714861852ull,6564284716173382975ull,7431641711380683486ull,
5930354027267144503ull,7960008410874295510ull,3042788754963080437ull,1585637229969582868ull,2828535324494588308ull,1980318352852969077ull,6860680106652005974ull,7137485081799358903ull,
4446559905925329750ull,112064718230027447ull,5027050166203214996ull,8789007311466423157ull,5240354716023005685ull,8395275065003879956ull,3517182702894202423ull,933639166589153750ull,
602950450399758034ull,3775534732870502707ull,8081971130871404816ull,5481889019817449201ull,9030346482859447409ull,4713373941376293776ull,370647126704196531ull,4116208084007846994ull,
7469113332713230003ull,6601406138767999314ull,2292735532829086065ull,2587905371539086992ull,1345379426006064144ull,3355401200587363313ull,7700397406948803538ull,6261752032728566835ull,
4823603603198064275ull,9136564507772074354ull,4217075945466112337ull,485659586792138416ull,4034312254212957232ull,848850972607671249ull,5731446595013999602ull,8336524268413547539ull,
3245233678218362610ull,1239081703546220819ull,6160804473723085104ull,7585447086313631441ull,6342548919878331473ull,7223274949958083504ull,2338409935795303315ull,2038102697739730034ull,
1793035491680439158ull,2655255362396996759ull,6959422166814676148ull,6678747529195019093ull,7921273411411876309ull,5896756564587157044ull,1556264030828725783ull,3000396857132943862ull,
8582637658083885847ull,5413572573028093174ull,1111639976481332437ull,3699195012258665268ull,150737612599939508ull,4480237100512796245ull,8818460242514759286ull,5069379958940844439ull,
8301446262652510334ull,5697002453405118367ull,811308419554590652ull,3997261728307851357ull,448258872920109789ull,4180450932742028604ull,9101344667125017887ull,4788733952703193854ull,
2075361565663127583ull,2375176776549754878ull,7258636602479048669ull,6377276708234557500ull,7620383230015650492ull,6195390427260335453ull,1276766084583466366ull,3282142358086691487ull,
2965177013633572251ull,1521394377481540218ull,5859355848869429849ull,7884648396842094008ull,6641204978658316088ull,6922371643425947865ull,2620177358011502842ull,1758591351447101211ull,
5107064338333865466ull,8855368920738863643ull,4515173241429723704ull,185323563352098265ull,3734556666356615001ull,1146367766414543032ull,5450831443535124635ull,8619404501421971322ull,
2411801801599032137ull,2108537972733056168ull,6417208513977975947ull,7293009827467168618ull,6085577509926160874ull,7516270730994599435ull,3171274459939165736ull,1169204967897651657ull,
5657070648989176616ull,8267073039549717705ull,3960636705705938154ull,778132015414362891ull,4291318829041942923ull,555819988240666218ull,4898546867069886025ull,9205457163736420776ull,
8893119811850659500ull,5139114811686185293ull,224129436460054894ull,4550672333562508943ull,1037680782831563791ull,3629318301239524334ull,8507410736096259021ull,5344396259518358572ull,
1482588506816786125ull,2929677924434714924ull,7846897507062001935ull,5827305377398275822ull,7034365405788404846ull,6747640160261272463ull,1867278333178307500ull,2725415721767562317ull,
1205900900799516068ull,3208604256988987973ull,7551069465741005414ull,6120868271824739719ull,7327383049032621831ull,6452357436695564518ull,2145659414520971461ull,2449273433534943012ull,
9170942131316344261ull,4863539807485053476ull,518840391415781895ull,4253705368048129510ull,741294253408393062ull,3923448753531000967ull,8232416168015693988ull,5621638076290434885ull,
5381517704024256577ull,8544882370750152608ull,3663691524516310915ull,1072829707260485730ull,4585471065658172130ull,259420195707890947ull,5175810743078173984ull,8930449607390606017ull,
2690758852012128288ull,1831845762258155457ull,6710802401174726626ull,6997177456532891651ull,5790325779130739331ull,7809284044625536354ull,2895162889565369665ull,1447581444782684832ull
};
public:
ull BKDRHash(string s,ull seed=131){
ull ans=0;
for(int i=0;i<s.length();i++){
ans=ans*seed+s[i];
}
return ans;
}
ull BKDRHash(char* s,ull seed=131){
ull ans=0;
while(*s){
ans=ans*seed+(*s++);
}
return ans;
}
ull APHash(string s){
ull ans=0;
for(int i=0;i<s.length();i++){
if(i&1){
ans^=~((ans<<11)^s[i]^(ans>>5));
}else{
ans^=(ans<<7)^s[i]^(ans>>3);
}
}
return ans;
}
ull APHash(char* s){
ull ans=0;
for(int i=0;s[i];i++){
if(i&1){
ans^=~((ans<<11)^s[i]^(ans>>5));
}else{
ans^=(ans<<7)^s[i]^(ans>>3);
}
}
return ans;
}
ull JSHash(string s,ull seed=1315423911){
ull ans=seed;
for(int i=0;i<s.length();i++){
ans^=(ans<<5)+s[i]+(ans>>2);
}
return ans;
}
ull JSHash(char* s,ull seed=1315423911){
ull ans=seed;
while(*s){
ans^=(ans<<5)+(*s++)+(ans>>2);
}
return ans;
}
ull RSHash(string s,ull a=63689,ull b=378551){
ull ans=0;
for(int i=0;i<s.length();i++){
ans=ans*a+s[i];
a*=b;
}
return ans;
}
ull RSHash(char* s,ull a=63689,ull b=378551){
ull ans=0;
while(*s){
ans=ans*a+(*s++);
a*=b;
}
return ans;
}
ull SDBMHash(string s){
ull ans=0;
for(int i=0;i<s.length();i++){
ans=s[i]+(ans<<6)+(ans<<16)-ans;
}
return ans;
}
ull SDBMHash(char* s){
ull ans=0;
while(*s){
ans=(*s++)+(ans<<6)+(ans<<16)-ans;
}
return ans;
}
ull PJWHash(string s){
ull ans=0,test=0;
for(int i=0;i<s.length();i++){
ans=(ans<<8)+s[i];
if(test=ans&0xff00000000000000){
ans=((ans^(test>>48))&(0xffffffffffffff));
}
}
return ans;
}
ull PJWHash(char* s){
ull ans=0,test=0;
while(*s){
ans=(ans<<8)+(*s++);
if(test=ans&0xff00000000000000){
ans=((ans^(test>>48))&(0xffffffffffffff));
}
}
return ans;
}
ull ELFHash(string s){
ull ans=0,x=0;
for(int i=0;i<s.length();i++){
ans=(ans<<5)+s[i];
if((x=ans&0xff00000000000000)){
ans^=x>>48;
ans&=~x;
}
}
return ans;
}
ull ELFHash(char* s){
ull ans=0,x=0;
while(*s){
ans=(ans<<5)+(*s++);
if((x=ans&0xff00000000000000)){
ans^=x>>48;
ans&=~x;
}
}
return ans;
}
ull DJBHash(string s){
ull ans=5381;
for(int i=0;i<s.length();i++){
ans+=(ans<<5)+s[i];
}
return ans;
}
ull DJBash(char* s){
ull ans=5381;
while(*s){
ans+=(ans<<5)+(*s++);
}
return ans;
}
ull DEKHash(string s){
ull ans=s.length();
for(int i=0;i<s.length();i++){
ans=(ans<<6)^(ans<<16)^s[i];
}
return ans;
}
ull DEKHash(char* s){
ull ans=0,i=0;
for(;*s;i++){
ans=(ans<<6)^(ans<<16)^s[i];
}
return ans^i;
}
ull BPHash(string s){
ull ans=s.length();
for(int i=0;i<s.length();i++){
ans=(ans<<7)^s[i];
}
return ans;
}
ull BPash(char* s){
ull ans=0,i=0;
for(;*s;i++){
ans=(ans<<7)^(*s++);
}
return ans^i;
}
ull FNVHash(string s,ull seed=0xcbf29ce484222325,ull fnvprime=0x100000001b3){
ull ans=seed;
for(int i=0;i<s.length();i++){
ans^=s[i];
ans*=fnvprime;
}
return ans;
}
ull FNVash(char* s,ull seed=0xcbf29ce484222325,ull fnvprime=0x100000001b3){
ull ans=seed;
while(*s){
ans^=(*s++);
ans*=fnvprime;
}
return ans;
}
ull javaHash(string s){
ull ans=0;
for(int i=0;i<s.length();i++){
ans=ans*31+s[i];
}
return ans;
}
ull javaHash(char* s){
ull ans=0;
while(*s){
ans=ans*31+(*s++);
}
return ans;
}
ull CRCHash(string s,ull seed=0xffffffffffffffffull) {
ull ans=seed;
for(int i=0;i<s.length();i++){
ans=CRCTable[(ans^s[i])&0xff]^(ans>>8);
}
return ans;
}
inline ull fmix64(ull k) {
k^=k>>33;
k*=0xff51afd7ed558ccdull;
k^=k>>33;
k*=0xc4ceb9fe1a85ec53ull;
k^=k>>33;
return k;
}
ull murmurHash(string s,ull seed=27777890035307ull){
ull h1=seed,h2=seed,k1,k2;
constexpr static ull c1=0x87c37b91114253d5ull,c2=0x4cf5ad432745937full;
for(int i=0;i<s.length();i+=2){
k1=s[i];
k2=s[i+1];
k1*=c1;
k1=(k1<<31|k1>>33);
k1*=c2;
h1^=k1;
h1=(h1<<27|h1>>37);
h1+=h2;
h1=h1*5+0x52dce729;
k2*=c2;
k2=(k2<<31|k2>>33);
k2*=c1;
h2^=k2;
h2=(h2<<27|h2>>37);
h2+=h1;
h2=h2*5+0x38495ab5;
}
if(s.length()&1){
k1=*(s.end()-1);
k1*=c1;
k1=(k1<<31|k1>>33);
k1*=c2;
h1^=k1;
h1=(h1<<27|h1>>37);
h1+=h2;
h1=h1*5+0x52dce729;
}
h1^=s.length();
h2^=s.length();
h1+=h2;
h2+=h1;
h1=fmix64(h1);
h2=fmix64(h2);
h1+=h2;
h2+=h1;
return h1+h2;
}
ull murmurHash(char* s,ull seed=27777890035307ull){
ull h1=seed,h2=seed,k1,k2,len=0;
constexpr static ull c1=0x87c37b91114253d5ull,c2=0x4cf5ad432745937full;
while(*s){
k1=*(s++);
k1*=c1;
k1=(k1<<31|k1>>33);
k1*=c2;
h1^=k1;
h1=(h1<<27|h1>>37);
h1+=h2;
h1=h1*5+0x52dce729;
len++;
if(!*s){
break;
}
k2=*(s++);
k2*=c2;
k2=(k2<<31|k2>>33);
k2*=c1;
h2^=k2;
h2=(h2<<27|h2>>37);
h2+=h1;
h2=h2*5+0x38495ab5;
len++;
}
h1^=len;
h2^=len;
h1+=h2;
h2+=h1;
h1=fmix64(h1);
h2=fmix64(h2);
h1+=h2;
h2+=h1;
return h1+h2;
}
};
```
### KMP
```cpp
vector<int> getLPS(string s){
vector<int> LPS(s.length());
for(int i=1,j=0;i<s.length();i++,j=LPS[i-1]){
while(j>0&&s[i]!=s[j]){
j=LPS[j-1];
}
if(s[i]==s[j]){
j++;
}
LPS[i]=j;
}
return LPS;
}
vector<int> stdKMP(string t,string s){
vector<int> LPS=getLPS(t),occurrence;
for(int i=0,j=0;i<s.length();i++){
while(j&&s[i]!=t[j]){
j=LPS[j-1];
}
if(s[i]==t[j]){
j++;
}
if(j==t.length()){
occurrence.push_back(i-j+1);
}
}
return occurrence;
}
vector<int> OIWikiKMP(string t,string s){
string str=t+'\n'+s;
vector<int> LPS=getLPS(str),occurrence;
for(int i=s.length()+1;i<str.length();i++){
if(LPS[i]==s.length()){
occurrence.push_back(i-2*s.length());
}
}
return occurrence;
}
__Pa(vector<int>) getLPSAndOccurrence(string t,string s){
string str=s+'\n'+t;
vector<int> LPS(s.length()),occurrence;
for(int i=1,j=0;i<str.length();i++){
while(j>0&&str[i]!=str[j]){
j=LPS[j-1];
}
if(str[i]==str[j]){
j++;
}
if(i<s.length()){
LPS[i]=j;
}
if(j==s.length()){
occurrence.push_back(i-2*s.length());
}
}
return {LPS,occurrence};
}
```
### Manachar
```cpp
string fillIn(string s){
string ans="#";
for(int i=0;i<s.length();i++){
ans.push_back(s[i]);
ans.push_back('#');
}
return '@'+ans+'`';
}
vector<int> manacher(string str){
string s=fillIn(str);
vector<int> p(s.length());
for(int i=1,r=0,c=0,k;i<s.length();i++){
if(i<r){
k=min(r-i,p[2*c-i]);
}else{
k=1;
}
while(s[i-k]==s[i+k]){
k++;
}
p[i]=k;
if(k+i>r){
r=k+i;
c=i;
}
}
return p;
}
```
## 高精度
### 不压位
```cpp
namespace BigInteger{
class bigInt{
//高精度定义
public:
typedef unsigned short value_type;
typedef const value_type const_value_type;
typedef value_type* pointer;
typedef const_value_type* const_pointer;
typedef value_type& reference;
typedef const_value_type& const_reference;
typedef __gnu_cxx::__normal_iterator<pointer,bigInt> reverse_iterator;
typedef __gnu_cxx::__normal_iterator<const_pointer,bigInt> const_reverse_iterator;
typedef std::reverse_iterator<const_reverse_iterator> const_iterator;
typedef std::reverse_iterator<reverse_iterator> iterator;
iterator begin();
iterator end();
reverse_iterator rbegin();
reverse_iterator rend();
const_iterator cbegin();
const_iterator cend();
const_reverse_iterator crbegin();
const_reverse_iterator crend();
bigInt& constructor(long long);
bigInt& constructor(const std::string&);
bigInt& constructor(const char*);
bigInt(long long=0);
bigInt(const std::string&);
bigInt(const char*);
bigInt(const bigInt&);
~bigInt();
bigInt& operator=(const bigInt&);
bigInt& add(const bigInt&);
bigInt& subtract(const bigInt&);
bigInt& multiply(const bigInt&);
bigInt& add(const long long&);
bigInt& subtract(const long long&);
bigInt& multiply(const long long&);
bigInt& divide(const bigInt&);
bigInt& mod(const bigInt&);
bigInt* divideAndRemainder(const bigInt&);
bigInt& divide(const long long);
bigInt& mod(const long long);
bigInt* divideAndRemainder(const long long);
bigInt& operator+=(const bigInt&);
bigInt& operator-=(const bigInt&);
bigInt& operator*=(const bigInt&);
bigInt& operator/=(const bigInt&);
bigInt& operator%=(const bigInt&);
bigInt& operator+=(const long long);
bigInt& operator-=(const long long);
bigInt& operator*=(const long long);
bigInt& operator/=(const long long);
bigInt& operator%=(const long long);
bigInt& operator++();
bigInt operator++(int);
bigInt& operator--();
bigInt operator--(int);
operator long long();
operator std::string();
operator bool();
bigInt& operator-();
friend bigInt operator+(const bigInt&,const bigInt&);
friend bigInt operator-(const bigInt&,const bigInt&);
friend bigInt operator*(const bigInt&,const bigInt&);
friend bigInt operator/(const bigInt&,const bigInt&);
friend bigInt operator%(const bigInt&,const bigInt&);
friend bigInt operator+(const bigInt&,const long long);
friend bigInt operator-(const bigInt&,const long long);
friend bigInt operator*(const bigInt&,const long long);
friend bigInt operator/(const bigInt&,const long long);
friend bigInt operator%(const bigInt&,const long long);
friend bool operator>(const bigInt&,const bigInt&);
friend bool operator<(const bigInt&,const bigInt&);
friend bool operator>=(const bigInt&,const bigInt&);
friend bool operator<=(const bigInt&,const bigInt&);
friend bool operator==(const bigInt&,const bigInt&);
friend bool operator!=(const bigInt&,const bigInt&);
friend bool operator>(const bigInt&,const long long&);
friend bool operator<(const bigInt&,const long long&);
friend bool operator>=(const bigInt&,const long long&);
friend bool operator<=(const bigInt&,const long long&);
friend bool operator==(const bigInt&,const long long&);
friend bool operator!=(const bigInt&,const long long&);
friend std::istream& operator>>(std::istream&,bigInt&);
friend std::ostream& operator<<(std::ostream&,const bigInt&);
unsigned short& operator[](size_t);
long long toInteger(bool=1) const;
std::string toString() const;
bool toBoolean() const;
size_t length() const;
size_t size() const;
int compare(const bigInt&) const;
void swap(bigInt&);
void clear();
void resize(size_t);
void setpositive(bool);
void pop();
void push(const unsigned short);
bool empty();
unsigned short front();
unsigned short back();
private:
unsigned short *__num=nullptr;
size_t __num_length=0,__num_size=0;
bool __flag=1;
bigInt **__new_bi_location=nullptr;
size_t __new_bi_location_length=0,__new_bi_location_size=0;
void __location_push(bigInt*);
size_t __newsize(unsigned short*&,size_t);
size_t __resize(unsigned short*&,size_t,size_t);
void __add(const bigInt&,const bigInt&,bigInt&);
void __subtract(const bigInt&,const bigInt&,bigInt&);
void __multiply(const bigInt&,const bigInt&,bigInt&);
void __divide_mod_bi(const bigInt&,const bigInt&,bigInt&,bigInt&);
void __divide_mod_li(const bigInt&,const long long,bigInt&,bigInt&);
};
//高精度实现
bigInt::iterator bigInt::begin(){
return iterator(this->rend());
}
bigInt::iterator bigInt::end(){
this->__num[-1]=0;
return iterator(this->rbegin());
}
bigInt::reverse_iterator bigInt::rbegin(){
return reverse_iterator(this->__num);
}
bigInt::reverse_iterator bigInt::rend(){
this->__num[this->__num_length]=0;
return reverse_iterator(this->__num+this->__num_length);
}
bigInt::const_iterator bigInt::cbegin(){
return const_iterator(this->crend());
}
bigInt::const_iterator bigInt::cend(){
this->__num[-1]=0;
return const_iterator(this->crbegin());
}
bigInt::const_reverse_iterator bigInt::crbegin(){
return const_reverse_iterator(this->__num);
}
bigInt::const_reverse_iterator bigInt::crend(){
this->__num[this->__num_length]=0;
return const_reverse_iterator(this->__num+this->__num_length);
}
bigInt& bigInt::constructor(long long num){
if(this->__num_size<20){
this->__num_size=this->__newsize(this->__num,20);
}
this->__num_length=0;
if(!num){
this->__flag=1;
this->__num[this->__num_length++]=0;
}else{
if(num<0){
this->__flag=0;
num=-num;
}else{
this->__flag=1;
}
while(num){
this->__num[this->__num_length++]=num%10;
num/=10;
}
}
return *this;
}
bigInt& bigInt::constructor(const std::string &str){
int start_index=0,str_length=str.length();
if(str[0]=='-'){
this->__flag=0;
start_index++;
}else{
this->__flag=1;
}
while(str[start_index]=='0'){
start_index++;
}
if(this->__num_size<str_length-start_index+1){
this->__num_size=this->__newsize(this->__num,str_length-start_index+1);
}
this->__num_length=0;
for(int i=str_length-1;i>=start_index;i--){
this->__num[this->__num_length++]=str[i]-'0';
}
if(!this->__num_length){
this->__num[this->__num_length++]=0;
}
return *this;
}
bigInt& bigInt::constructor(const char *str){
int start_index=0,str_length=strlen(str);
if(str[0]=='-'){
this->__flag=0;
start_index++;
}else{
this->__flag=1;
}
while(str[start_index]=='0'){
start_index++;
}
if(this->__num_size<str_length-start_index+1){
this->__num_size=this->__newsize(this->__num,str_length-start_index+1);
}
this->__num_length=0;
for(int i=str_length-1;i>=start_index;i--){
this->__num[this->__num_length++]=str[i]-'0';
}
if(!this->__num_length){
this->__num[this->__num_length++]=0;
}
return *this;
}
bigInt::bigInt(long long num){
this->constructor(num);
}
bigInt::bigInt(const std::string &str){
this->constructor(str);
}
bigInt::bigInt(const char *str){
this->constructor(str);
}
bigInt::bigInt(const bigInt &bi){
this->__num_size=this->__newsize(this->__num,bi.__num_size);
memcpy(this->__num,bi.__num,bi.__num_length*sizeof(unsigned short));
this->__num_length=bi.__num_length;
this->__flag=bi.__flag;
}
bigInt::~bigInt(){
delete[] this->__num;
for(size_t i=0;i<this->__new_bi_location_length;i++){
delete[] this->__new_bi_location[i];
}
delete[] this->__new_bi_location;
}
bigInt& bigInt::operator=(const bigInt &bi){
this->__num_size=this->__newsize(this->__num,bi.__num_size);
memcpy(this->__num,bi.__num,bi.__num_length*sizeof(unsigned short));
this->__num_length=bi.__num_length;
this->__flag=bi.__flag;
return *this;
}
bigInt& bigInt::operator-(){
if(!(this->__num_length==1&&this->__num[0]==0)){
this->__flag=!this->__flag;
}
return *this;
}
bigInt& bigInt::add(const bigInt &bi){
if(bi.__flag==this->__flag){
this->__add(*this,bi,*this);
}else if(bi.__flag){
this->__flag=1;
this->swap(bigInt(bi).subtract(*this));
}else{
bigInt &bi_map=const_cast<bigInt&>(bi);
bi_map.__flag=1;
this->subtract(bi_map);
bi_map.__flag=0;
}
return *this;
}
bigInt& bigInt::add(const long long &bi){
return this->add(bigInt(bi));
}
bigInt& bigInt::subtract(const bigInt &bi){
if(bi.__flag==this->__flag){
int _cmp=this->compare(bi);
if(_cmp>0){
if(this->__flag){
this->__subtract(*this,bi,*this);
}else{
this->__subtract(bi,*this,*this);
}
this->__flag=1;
}else if(_cmp<0){
if(this->__flag){
this->__subtract(bi,*this,*this);
}else{
this->__subtract(*this,bi,*this);
}this->__flag=0;
}else{
this->clear();
}
}else{
this->__add(*this,bi,*this);
}
return *this;
}
bigInt& bigInt::subtract(const long long &bi){
return this->subtract(bigInt(bi));
}
bigInt& bigInt::multiply(const bigInt &bi){
if(this->__num_length==1&&this->__num[0]==0||bi.__num_length==1&&bi.__num[0]==0){
this->clear();
}else if(this->__num_length==1&&this->__num[0]==1){
bool this_flag=this->__flag;
bigInt ans(bi);
this->swap(ans);
this->__flag=bi.__flag?this_flag:!this_flag;
}else if(bi.__num_length==1&&bi.__num[0]==1){
this->__flag=bi.__flag?this->__flag:!this->__flag;
return *this;
}else{
bool this_flag=this->__flag;
this->__multiply(*this,bi,*this);
this->__flag=this_flag!=bi.__flag?0:1;
}
return *this;
}
bigInt& bigInt::multiply(const long long &bi){
return this->multiply(bigInt(bi));
}
bigInt& bigInt::divide(const bigInt &bi){
if(bi.__num_length==1&&bi.__num[0]==1){
this->__flag=bi.__flag==this->__flag;
}else{
this->swap(this->divideAndRemainder(bi)[0]);
}
return *this;
}
bigInt& bigInt::mod(const bigInt &bi){
if(bi.__num_length==1&&bi.__num[0]==1){
this->clear();
}else{
this->swap(this->divideAndRemainder(bi)[1]);
}
return *this;
}
bigInt* bigInt::divideAndRemainder(const bigInt &bi){
bigInt* ans=new bigInt[2];
this->__location_push(ans);
if(bi.__num_length==1&&bi.__num[0]==0){
abort();
}
if(bi.__num_length==1&&bi.__num[0]==1){
bigInt temp(*this);
ans[0].swap(temp);
ans[0].__flag=bi.__flag==this->__flag;
}else{
bool this_flag=this->__flag;
if(bi.__flag!=this->__flag){
this->__flag=bi.__flag;
}
int _cmp=this->compare(bi);
if(_cmp>0){
if(bi.__flag){
this->__divide_mod_bi(*this,bi,ans[0],ans[1]);
ans[0].__flag=this_flag==bi.__flag;
ans[1].__flag=this_flag;
}else{
bigInt temp(*this);
ans[1].swap(temp);
}
}else if(_cmp<0){
if(bi.__flag){
bigInt temp(*this);
ans[1].swap(temp);
}else{
this->__divide_mod_bi(*this,bi,ans[0],ans[1]);
ans[0].__flag=this_flag==bi.__flag;
ans[1].__flag=this_flag;
}
}else{
ans[0]=this_flag==bi.__flag?1:-1;
}
this->__flag=this_flag;
}
return ans;
}
bigInt& bigInt::divide(const long long li){
if(li==1||li==-1){
this->__flag=li>0?this->__flag:!this->__flag;
}else{
this->swap(this->divideAndRemainder(li)[0]);
}
return *this;
}
bigInt& bigInt::mod(const long long li){
if(li==1||li==-1){
this->clear();
}else{
this->swap(this->divideAndRemainder(li)[1]);
}
return *this;
}
bigInt* bigInt::divideAndRemainder(const long long li){
bigInt* ans=new bigInt[2];
this->__location_push(ans);
if(li==0){
abort();
}
bool li_flag=li>0;
if(li==1||li==-1){
bigInt temp(*this);
ans[0].swap(temp);
ans[0].__flag=li_flag==this->__flag;
}else{
bigInt bi(li);
if(bi.length()>18){
this->__divide_mod_bi(*this,bi,ans[0],ans[1]);
}else{
this->__divide_mod_li(*this,(li>0?li:-li),ans[0],ans[1]);
}
ans[0].__flag=this->__flag==li_flag;
ans[1].__flag=this->__flag;
}
return ans;
}
bigInt& bigInt::operator+=(const bigInt &bi){
this->add(bi);
return *this;
}
bigInt& bigInt::operator-=(const bigInt &bi){
this->subtract(bi);
return *this;
}
bigInt& bigInt::operator*=(const bigInt &bi){
this->multiply(bi);
return *this;
}
bigInt& bigInt::operator/=(const bigInt &bi){
this->divide(bi);
return *this;
}
bigInt& bigInt::operator%=(const bigInt &bi){
this->mod(bi);
return *this;
}
bigInt& bigInt::operator+=(const long long li){
this->add(li);
return *this;
}
bigInt& bigInt::operator-=(const long long li){
this->subtract(li);
return *this;
}
bigInt& bigInt::operator*=(const long long li){
this->multiply(li);
return *this;
}
bigInt& bigInt::operator/=(const long long li){
this->divide(li);
return *this;
}
bigInt& bigInt::operator%=(const long long li){
this->mod(li);
return *this;
}
bigInt& bigInt::operator++(){
this->add(1);
return *this;
}
bigInt bigInt::operator++(int){
bigInt ans(*this);
this->add(1);
return *this;
}
bigInt& bigInt::operator--(){
this->subtract(1);
return *this;
}
bigInt bigInt::operator--(int){
bigInt ans(*this);
this->subtract(1);
return *this;
}
bigInt::operator long long(){
return this->toInteger(0);
}
bigInt::operator std::string(){
return this->toString();
}
bigInt::operator bool(){
return this->toBoolean();
}
bigInt operator+(const bigInt &bi_a,const bigInt &bi_b){
bigInt ans(bi_a);
ans.add(bi_b);
return ans;
}
bigInt operator-(const bigInt &bi_a,const bigInt &bi_b){
bigInt ans(bi_a);
ans.subtract(bi_b);
return ans;
}
bigInt operator*(const bigInt &bi_a,const bigInt &bi_b){
bigInt ans(bi_a);
ans.multiply(bi_b);
return ans;
}
bigInt operator/(const bigInt &bi_a,const bigInt &bi_b){
bigInt ans(bi_a);
ans.divide(bi_b);
return ans;
}
bigInt operator%(const bigInt &bi_a,const bigInt &bi_b){
bigInt ans(bi_a);
ans.mod(bi_b);
return ans;
}
bigInt operator+(const bigInt &bi_a,const long long &li_b){
bigInt ans(bi_a);
ans.add(li_b);
return ans;
}
bigInt operator-(const bigInt &bi_a,const long long &li_b){
bigInt ans(bi_a);
ans.subtract(li_b);
return ans;
}
bigInt operator*(const bigInt &bi_a,const long long &li_b){
bigInt ans(bi_a);
ans.multiply(li_b);
return ans;
}
bigInt operator/(const bigInt &bi_a,const long long li_b){
bigInt ans(bi_a);
ans.divide(li_b);
return ans;
}
bigInt operator%(const bigInt &bi_a,const long long li_b){
bigInt ans(bi_a);
ans.mod(li_b);
return ans;
}
bool operator>(const bigInt &bi_a,const bigInt &bi_b){
return bi_a.compare(bi_b)>0;
}
bool operator<(const bigInt &bi_a,const bigInt &bi_b){
return bi_a.compare(bi_b)<0;
}
bool operator>=(const bigInt &bi_a,const bigInt &bi_b){
int _cmp=bi_a.compare(bi_b);
return(_cmp==1||_cmp==0);
}
bool operator<=(const bigInt &bi_a,const bigInt &bi_b){
int _cmp=bi_a.compare(bi_b);
return(_cmp==-1||_cmp==0);
}
bool operator==(const bigInt &bi_a,const bigInt &bi_b){
return bi_a.compare(bi_b)==0;
}
bool operator!=(const bigInt &bi_a,const bigInt &bi_b){
return !(bi_a.compare(bi_b)==0);
}
bool operator>(const bigInt &bi_a,const long long &li_b){
return bi_a.compare(li_b)>0;
}
bool operator<(const bigInt &bi_a,const long long &li_b){
return bi_a.compare(li_b)<0;
}
bool operator>=(const bigInt &bi_a,const long long &li_b){
int _cmp=bi_a.compare(li_b);
return(_cmp==1||_cmp==0);
}
bool operator<=(const bigInt &bi_a,const long long &li_b){
int _cmp=bi_a.compare(li_b);
return(_cmp==-1||_cmp==0);
}
bool operator==(const bigInt &bi_a,const long long &li_b){
return bi_a.compare(li_b)==0;
}
bool operator!=(const bigInt &bi_a,const long long &li_b){
return !(bi_a.compare(li_b)==0);
}
std::istream& operator>>(std::istream& _cin,bigInt &bi){
std::string str;
_cin>>str;
bi.constructor(str);
return _cin;
}
std::ostream& operator<<(std::ostream& _cout,const bigInt &bi){
if(!bi.__flag){
_cout<<'-';
}
for(int i=bi.__num_length-1;i>=0;i--){
_cout<<bi.__num[i];
}
return _cout;
}
unsigned short& bigInt::operator[](size_t index){
return this->__num[this->__num_length-index-1];
}
long long bigInt::toInteger(bool check_overflow) const{
if(!check_overflow||(this->__num_length<19||(this->__num_length==19&&(this->__flag?this->compare(bigInt("9223372036854775807"))<=0:this->compare(bigInt("-9223372036854775807"))>=0)))){
long long ans=0,cnt=1;
for(int i=0;i<this->__num_length;i++,cnt*=10){
ans+=cnt*this->__num[i];
}
return this->__flag?ans:-ans;
}else{
return 0LL;
}
}
std::string bigInt::toString() const{
std::string ans;
if(!this->__flag){
ans.push_back('-');
}
for(int i=this->__num_length-1;i>=0;i--){
ans.push_back(this->__num[i]+'0');
}
return ans;
}
bool bigInt::toBoolean() const{
return !(this->__num_length==1&&this->__num[0]==0);
}
size_t bigInt::length() const{
return this->__num_length;
}
size_t bigInt::size() const{
return this->__num_size;
}
void bigInt::pop(){
if(this->__num_length>1){
this->__num_length--;
}else{
this->clear();
}
}
void bigInt::push(const unsigned short num){
if(this->__num_length==1&&this->__num[0]==0){
this->__num_length--;
}
if(this->__num_length>=this->__num_size){
this->__num_size=(size_t)(this->__num_size*1.5);
this->__num_size=this->__resize(this->__num,this->__num_size==1?2:this->__num_size,this->__num_length);
}
this->__num[this->__num_length++]=num;
}
bool bigInt::empty(){
return this->__num_length==1&&this->__num[0]==0;
}
unsigned short bigInt::front(){
return this->__num[this->__num_length-1];
}
unsigned short bigInt::back(){
return this->__num[0];
}
int bigInt::compare(const bigInt &bi) const{
if(this->__flag!=bi.__flag){
return this->__flag?1:-1;
}else{
int ans=this->__flag?1:-1;
if(this->__num_length>bi.__num_length){
return ans;
}else if(this->__num_length<bi.__num_length){
return -ans;
}else{
for(int i=this->__num_length-1;i>=0;i--){
if(this->__num[i]<bi.__num[i]){
return -ans;
}else if(this->__num[i]>bi.__num[i]){
return ans;
}
}
return 0;
}
}
}
void bigInt::swap(bigInt &bi){
std::swap(this->__flag,bi.__flag);
std::swap(this->__num_size,bi.__num_size);
std::swap(this->__num_length,bi.__num_length);
std::swap(this->__num,bi.__num);
std::swap(this->__new_bi_location_size,bi.__new_bi_location_size);
std::swap(this->__new_bi_location_length,bi.__new_bi_location_length);
std::swap(this->__new_bi_location,bi.__new_bi_location);
}
void bigInt::clear(){
this->__num_length=1;
this->__num[0]=0;
this->__flag=1;
}
void bigInt::resize(size_t size){
this->__num_size=this->__resize(this->__num,size,this->__num_size);
this->__num_length=min(this->__num_size,this->__num_length);
}
void bigInt::setpositive(bool flag){
if(this->__num_length==1&&this->__num[0]==0){
return;
}
this->__flag=flag;
}
void bigInt::__location_push(bigInt* new_bi_location){
if(this->__new_bi_location_length>=this->__new_bi_location_size){
this->__new_bi_location_size*=1.5;
this->__new_bi_location_size=this->__new_bi_location_size?this->__new_bi_location_size:4;
bigInt** new_bi_location_list=new bigInt* [this->__new_bi_location_size]{NULL};
memcpy(new_bi_location_list,this->__new_bi_location,this->__new_bi_location_length*sizeof(bigInt*));
delete[] this->__new_bi_location;
this->__new_bi_location=new_bi_location_list;
}
this->__new_bi_location[this->__new_bi_location_length++]=new_bi_location;
}
size_t bigInt::__newsize(unsigned short*& num,size_t length){
delete[] num;
num=new unsigned short[length]{0};
return length;
}
size_t bigInt::__resize(unsigned short*& num,size_t length,size_t prelen){
unsigned short* new_num=new unsigned short[length]{0};
memcpy(new_num,num,(prelen>length?length:prelen)*sizeof(unsigned short));
delete[] num;
num=new_num;
return length;
}
void bigInt::__add(const bigInt &a,const bigInt &b,bigInt &c){
int a_length=a.__num_length,b_length=b.__num_length,min_length=a_length<b_length?(b_length+1>c.__num_size?(c.__num_size=this->__resize(c.__num,b_length+1,c.__num_length)):0,a_length):(a_length+1>c.__num_size?(c.__num_size=this->__resize(c.__num,a_length+1,c.__num_length)):0,b_length);
c.__num_length=0;
unsigned short sum,t=0;
for(int i=0;i<min_length;i++){
sum=a.__num[i]+b.__num[i]+t;
t=sum/10;
c.__num[c.__num_length++]=sum%10;
}
if(a_length>b_length){
for(int i=min_length;i<a_length;i++){
sum=a.__num[i]+t;
t=sum/10;
c.__num[c.__num_length++]=sum%10;
}
}else if(a_length<b_length){
for(int i=min_length;i<b_length;i++){
sum=b.__num[i]+t;
t=sum/10;
c.__num[c.__num_length++]=sum%10;
}
}
if(t){
c.__num[c.__num_length++]=t;
}
}
void bigInt::__subtract(const bigInt &a,const bigInt &b,bigInt &c){
int a_length=a.__num_length,b_length=b.__num_length;
if(c.__num_size<a_length){
c.__num_size=this->__resize(c.__num,a_length,c.__num_size);
}
c.__num_length=0;
short sum,t=0;
for(int i=0;i<b_length;i++){
sum=a.__num[i]-b.__num[i]-t;
t=0;
c.__num[c.__num_length++]=sum>=0?sum:(t=1,sum+10);
}
if(a_length!=b_length){
for(int i=b_length;i<a_length;i++){
sum=a.__num[i]-t;
t=0;
c.__num[c.__num_length++]=sum>=0?sum:(t=1,sum+10);
}
}
while(c.__num_length>1&&c.__num[c.__num_length-1]==0){
c.__num_length--;
}
}
void bigInt::__multiply(const bigInt &a,const bigInt &b,bigInt &c){
int a_length=a.__num_length,b_length=b.__num_length;
bigInt ans;
ans.__num_size=this->__newsize(ans.__num,a_length+b_length+1);
ans.__num_length=a_length+b_length;
unsigned short t;
for(int i=0;i<a_length;i++){
t=0;
for(int j=0;j<b_length;j++){
ans.__num[i+j]=a.__num[i]*b.__num[j]+ans.__num[i+j]+t;
t=ans.__num[i+j]/10;
ans.__num[i+j] %= 10;
}
ans.__num[b_length+i]=t;
}
while(ans.__num_length>1&&ans.__num[ans.__num_length-1]==0){
ans.__num_length--;
}
c.swap(ans);
}
void bigInt::__divide_mod_bi(const bigInt &a,const bigInt &b,bigInt ÷r,bigInt &remainder){
bigInt temp,cp_a(a);
temp.__num_size=this->__newsize(temp.__num,a.__num_length+b.__num_length+1);
remainder.swap(cp_a);
temp.__flag=remainder.__flag=1;
size_t prelen=divider.__num_length;
divider.__num_length=a.__num_length-b.__num_length+1;
if(divider.__num_length>divider.__num_size){
divider.__num_size=this->__resize(divider.__num,divider.__num_length+1,prelen);
}
for(int i=divider.__num_length-1;i>=0;i--){
memset(temp.__num,0,sizeof(i+b.__num_length));
for(size_t j=0;j<b.__num_length;j++){
temp.__num[j+i]=b.__num[j];
}
temp.__num_length=b.__num_length+i;
while(remainder.compare(temp)>=0){
divider.__num[i]++;
this->__subtract(remainder,temp,remainder);
}
}
while(divider.__num_length>1&÷r.__num[divider.__num_length-1]==0){
divider.__num_length--;
}
}
void bigInt::__divide_mod_li(const bigInt &a,const long long b,bigInt ÷r,bigInt &remainder){
long long t=0;
divider.__num_length=a.__num_length;
divider.__num_size=this->__newsize(divider.__num,divider.__num_length+1);
for(int i=divider.__num_length-1;i>=0;i--){
divider.__num[i]=(t*10+a.__num[i])/b;
t=(t*10+a.__num[i])%b;
}
while(divider.__num_length>1&÷r.__num[divider.__num_length-1]==0){
divider.__num_length--;
}
bigInt ans(t);
remainder.swap(ans);
}
}
```
### 压位
```cpp
class ZeroDivisionError:public std::runtime_error{
public:
ZeroDivisionError():runtime_error("Division by zero"){}
};
class FFTLimitExceededError:public std::runtime_error{
public:
FFTLimitExceededError():runtime_error("FFT size limit exceeded"){}
};
class NegativeRadicandError:public std::runtime_error{
public:
NegativeRadicandError():runtime_error("Negative radicand in root operation"){}
};
class BigInteger{
protected:
static constexpr int WIDTH=8;
static constexpr long long BASE=1e8;
static constexpr long long FFT_LIMIT=32;
static constexpr long long NEWTON_DIV_LIMIT=64;
static constexpr long long NEWTON_DIV_MIN_LEVEL=16;
static constexpr long long NEWTON_SQRT_LIMIT=48;
static constexpr long long NEWTON_SQRT_MIN_LEVEL=5;
static constexpr size_t POOL_CHUNK_SIZE=1024;
long long* digits;
int capacity,size;
bool flag;
inline void push(const long long&);
inline void pop();
inline void resize(const int&);
inline int compare(const BigInteger&)const;
inline int compare(const long long&)const;
BigInteger& build_binary(const std::vector<bool>&);
static inline BigInteger fft_mul(const BigInteger&,const BigInteger&);
BigInteger newton_inv(int)const;
std::pair<BigInteger,BigInteger> newton_div(const BigInteger&)const;
BigInteger newton_invsqrt()const;
BigInteger sqrt_normal()const;
std::vector<long long*> memory_pool;
inline long long*allocate_digits(size_t);
inline void deallocate_digits(long long*,size_t);
public:
void reserve(const int&);
void clear();
~BigInteger()=default;
int _digit_len()const;
friend std::ostream&operator<<(std::ostream& out,const BigInteger& x){
if(!x.flag){
out<<'-';
}
out<<x.digits[x.size];
for(int i=x.size-1;i>=1;i--){
out<<std::setw(WIDTH)<<std::setfill('0')<<x.digits[i];
}
return out;
}
friend std::istream&operator>>(std::istream& in,BigInteger& x){
std::string s;
in>>s;
x=s;
return in;
}
BigInteger():digits(nullptr),flag(1){
*this=0ll;
}
BigInteger(const BigInteger& x):digits(nullptr){
*this=x;
}
BigInteger(const long long& x):digits(nullptr){
*this=x;
}
BigInteger(const std::string&s):digits(nullptr){
*this=s;
}
BigInteger(const std::vector<bool>&b):digits(nullptr){
*this=b;
}
template<class T> BigInteger(const T&begin,const T&end):digits(nullptr){
*this=std::vector<bool>(begin,end);
}
BigInteger(const long long*in,int len):digits(nullptr),flag(1){
while(len>0&&in[len-1]==0){
len--;
in++;
}
size=len;
digits=allocate_digits(len+1);
for(int i=0;i<len;i++){
digits[i+1]=in[i];
}
}
BigInteger& operator=(const BigInteger&);
BigInteger& operator=(const long long&);
BigInteger& operator=(const std::string&);
BigInteger& operator=(const std::vector<bool>&);
BigInteger& operator=(const __int128&);
std::string to_string()const;
long long to_long_long()const;
std::vector<bool> to_binary()const;
__int128 to_int128()const;
BigInteger operator-()const;
BigInteger operator~()const;
BigInteger abs()const;
operator std::string()const;
operator long long()const;
operator std::vector<bool>()const;
operator __int128()const;
bool operator==(const BigInteger&)const;
bool operator!=(const BigInteger&)const;
bool operator>=(const BigInteger&)const;
bool operator<=(const BigInteger&)const;
bool operator>(const BigInteger&)const;
bool operator<(const BigInteger&)const;
bool operator==(const long long&)const;
bool operator!=(const long long&)const;
bool operator>=(const long long&)const;
bool operator<=(const long long&)const;
bool operator>(const long long&)const;
bool operator<(const long long&)const;
#if __cplusplus>201703L
auto operator<=> (const BigInteger&)const;
auto operator<=> (const long long&)const;
#endif
BigInteger div2()const;
std::pair<BigInteger,BigInteger> divmod(const BigInteger&,bool=false)const;
BigInteger operator+(const long long&)const;
BigInteger operator+(const BigInteger&)const;
BigInteger operator-(const long long&)const;
BigInteger operator-(const BigInteger&)const;
BigInteger operator*(const long long&)const;
BigInteger operator*(const BigInteger&)const;
BigInteger operator/(const long long&)const;
BigInteger operator/(const BigInteger&)const;
BigInteger operator%(const long long&)const;
BigInteger operator%(const BigInteger&)const;
BigInteger pow(const long long&)const;
template<typename T> BigInteger pow(const long long&,const T&)const;
BigInteger root(const long long& =2)const;
BigInteger sqrt()const;
BigInteger gcd(const BigInteger&)const;
BigInteger lcm(const BigInteger&)const;
inline BigInteger _move_l(int)const;
inline BigInteger _move_r(int)const;
BigInteger& operator+=(const long long&);
BigInteger& operator+=(const BigInteger&);
BigInteger& operator-=(const long long&);
BigInteger& operator-=(const BigInteger&);
BigInteger& operator*=(long long);
BigInteger& operator*=(const BigInteger&);
BigInteger& operator/=(const long long&);
BigInteger& operator/=(const BigInteger&);
BigInteger& operator%=(const long long&);
BigInteger& operator%=(const BigInteger&);
BigInteger operator<<(const long long&);
BigInteger operator>>(const long long&);
BigInteger& operator<<=(const long long&);
BigInteger& operator>>=(const long long&);
BigInteger operator&(const BigInteger&);
BigInteger operator|(const BigInteger&);
BigInteger operator^(const BigInteger&);
BigInteger& operator&=(const BigInteger&);
BigInteger& operator|=(const BigInteger&);
BigInteger& operator^=(const BigInteger&);
BigInteger& operator++();
BigInteger operator++(int);
BigInteger& operator--();
BigInteger operator--(int);
static BigInteger random(const int&);
};
inline void BigInteger::push(const long long& val){
if(size==capacity){
int new_capacity=(capacity<256)?capacity*2:static_cast<int>(std::pow(capacity,1.125));
long long*new_digits=allocate_digits(new_capacity+1);
memcpy(new_digits,digits,sizeof(long long)*(capacity+1));
deallocate_digits(digits,capacity+1);
digits=new_digits;
capacity=new_capacity;
}
digits[++size]=val;
}
inline void BigInteger::pop(){
digits[size--]=0;
}
inline void BigInteger::resize(const int&sz){
reserve(sz);
size=sz;
}
inline int BigInteger::compare(const BigInteger& x)const{
if(flag&&!x.flag){
return 1;
}
if(!flag&&x.flag){
return-1;
}
int sgn=(flag&&x.flag?1:-1);
if(size>x.size){
return sgn;
}
if(size<x.size){
return -sgn;
}
for(int i=size;i>=1;i--){
if(digits[i]>x.digits[i]){
return sgn;
}
if(digits[i]<x.digits[i]){
return -sgn;
}
}
return 0;
}
inline int BigInteger::compare(const long long& x)const{
if(flag&&x>=0){
return 1;
}
if(!flag&&x<0){
return -1;
}
int sgn=(flag&&x<0?1:-1);
std::string s=std::to_string(x);
if(size>s.length()-(x<0)){
return sgn;
}
if(size<s.length()-(x<0)){
return -sgn;
}
for(int i=size;i>=1;i--){
if(digits[i]>s[i-1]-'0'){
return sgn;
}
if(digits[i]<s[i-1]-'0'){
return -sgn;
}
}
return 0;
}
BigInteger& BigInteger::build_binary(const std::vector<bool>&b){
*this=0ll;
if(b.empty()||(b.size()==1&&b[0]==0)){
return *this;
}
BigInteger pw2=1;
for(int i=b.size()-1;i>=0;i--,pw2+=pw2){
if(b[i]){
*this+=pw2;
}
}
return *this;
}
inline long long*BigInteger::allocate_digits(size_t size){
for(auto it=memory_pool.begin();it!=memory_pool.end();++it){
size_t*block_size=reinterpret_cast<size_t*>(*it)-1;
if(*block_size>=size){
long long*block=*it;
memory_pool.erase(it);
memset(block,0,size*sizeof(long long));
return block;
}
}
size_t*mem=static_cast<size_t*>(::operator new(sizeof(size_t)+size*sizeof(long long)));
*mem=size;
long long*ptr=reinterpret_cast<long long*>(mem+1);
memset(ptr,0,size*sizeof(long long));
return ptr;
}
inline void BigInteger::deallocate_digits(long long*ptr,size_t size){
if(!ptr){
return;
}
size_t*block_size=reinterpret_cast<size_t*>(ptr)-1;
if(*block_size>=POOL_CHUNK_SIZE){
memory_pool.push_back(ptr);
}else{
::operator delete(block_size);
}
}
void BigInteger::reserve(const int&sz){
if(sz<0){
return;
}
if(digits!=nullptr){
deallocate_digits(digits,capacity+1);
}
capacity=sz;
size=0;
digits=allocate_digits(sz+1);
}
void BigInteger::clear(){
deallocate_digits(digits,capacity+1);
digits=nullptr;
size=capacity=0;
}
int BigInteger::_digit_len()const{
return size;
}
BigInteger& BigInteger::operator=(const BigInteger& x){
if(this!=&x){
long long*new_digits=allocate_digits(x.size+1);
deallocate_digits(digits,capacity+1);
digits=new_digits;
capacity=x.size;
flag=x.flag;
size=x.size;
memcpy(digits,x.digits,sizeof(long long)*(x.size+1));
}
return *this;
}
BigInteger& BigInteger::operator=(const long long& x){
flag=(x>=0),reserve(4);
if(x==0){
return size=1,digits[1]=0,*this;
}
if(x==LLONG_MIN){
return *this="-9223372036854775808";
}
long long n=std::abs(x);
do{
push(n%BASE),n/=BASE;
}while(n);
return *this;
}
BigInteger& BigInteger::operator=(const std::string&s){
flag=1,reserve(s.size()/WIDTH+1);
if(s.empty()||s=="-"){
return*this=0ll;
}
int i=0;
if(s[0]=='-'){
flag=false,i++;
}
for(int j=s.size()-1;j>=i;j-=WIDTH){
int start=std::max(i,j-WIDTH+1),len=j-start+1;
push(stoll(s.substr(start,len)));
}
while(size>1&&digits[size]==0){
pop();
}
return *this;
}
BigInteger& BigInteger::operator=(const std::vector<bool>&a){
if(a==std::vector<bool>{0ll}) return*this=0ll;
std::vector<bool> res;
if(a[0]==0){
return build_binary(a);
}
res.resize(a.size());
for(int i=0;i<(int) a.size();++i){
res[i]=!a[i];
}
BigInteger x;
x.build_binary(res);
return *this=-x-1;
}
BigInteger& BigInteger::operator=(const __int128&x){
flag=(x>=0),reserve(8);
if(x==0){
return size=1,digits[1]=0,*this;
}
__int128 n=x>=0?x:-x;
do{
push(n%BASE);
n/=BASE;
}while(n);
return *this;
}
std::string BigInteger::to_string()const{
std::stringstream ss;
ss<<*this;
return ss.str();
}
long long BigInteger::to_long_long()const{
return stoll(to_string());
}
std::vector<bool> BigInteger::to_binary()const{
if(*this==0)
return{0,0};
std::vector<bool> res;
if(flag){
for(BigInteger x=*this;x!=0;x=x.div2()){
res.emplace_back(x.digits[1]&1);
}
res.emplace_back(0);
reverse(res.begin(),res.end());
return res;
}else{
for(BigInteger x=-*this-1;x!=0;x=x.div2()){
res.emplace_back(!(x.digits[1]&1));
}
res.emplace_back(1);
reverse(res.begin(),res.end());
return res;
}
};
__int128 BigInteger::to_int128()const{
__int128 res=0;
for(int i=size;i>=1;i--){
res=res*BASE+digits[i];
}
return res;
}
BigInteger BigInteger::operator-()const{
if(*this==0){
return 0;
}
BigInteger res=*this;
res.flag=!flag;
return res;
}
BigInteger BigInteger::operator~()const{
return -(*this)-1ll;
}
BigInteger BigInteger::abs()const{
BigInteger res=*this;
res.flag=1;
return res;
}
BigInteger::operator std::string()const{
std::stringstream ss;
ss<<*this;
return ss.str();
}
BigInteger::operator long long()const{
return stoll(to_string());
}
BigInteger::operator std::vector<bool>()const{
if(*this==0)
return{0,0};
std::vector<bool> res;
if(flag){
for(BigInteger x=*this;x!=0;x=x.div2()){
res.emplace_back(x.digits[1]&1);
}
res.emplace_back(0);
reverse(res.begin(),res.end());
return res;
}else{
for(BigInteger x=-*this-1;x!=0;x=x.div2()){
res.emplace_back(!(x.digits[1]&1));
}
res.emplace_back(1);
reverse(res.begin(),res.end());
return res;
}
};
BigInteger::operator __int128()const{
__int128 res=0;
for(int i=size;i>=1;i--){
res=res*BASE+digits[i];
}
return res;
}
bool BigInteger::operator==(const BigInteger& x)const{
return !compare(x);
}
bool BigInteger::operator!=(const BigInteger& x)const{
return compare(x);
}
bool BigInteger::operator>=(const BigInteger& x)const{
return compare(x)>=0;
}
bool BigInteger::operator<=(const BigInteger& x)const{
return compare(x)<=0;
}
bool BigInteger::operator>(const BigInteger& x)const{
return compare(x)>0;
}
bool BigInteger::operator<(const BigInteger& x)const{
return compare(x)<0;
}
bool BigInteger::operator==(const long long& x)const{
return !compare(x);
}
bool BigInteger::operator!=(const long long& x)const{
return compare(x);
}
bool BigInteger::operator>=(const long long& x)const{
return compare(x)>=0;
}
bool BigInteger::operator<=(const long long& x)const{
return compare(x)<=0;
}
bool BigInteger::operator>(const long long& x)const{
return compare(x)>0;
}
bool BigInteger::operator<(const long long& x)const{
return compare(x)<0;
}
#if __cplusplus>201703L
auto BigInteger::operator<=> (const BigInteger& x)const{
return compare(x);
}
auto BigInteger::operator<=> (const long long& x)const{
return compare(x);
}
#endif
BigInteger BigInteger::operator+(const BigInteger& x)const{
if(!x.flag){
return *this-x.abs();
}
if(!flag){
return x-abs();
}
BigInteger res;
res.flag=1;
int n=std::max(size,x.size)+1;
res.reserve(n);
long long carry=0;
for(int i=1;i<=n;i++){
long long d1=i<=size?digits[i]:0,d2=i<=x.size?x.digits[i]:0;
res.push(d1+d2+carry);
carry=res.digits[i]/BASE;
res.digits[i]%=BASE;
}
while(res.size>1&&res.digits[res.size]==0){
res.pop();
}
return res;
}
BigInteger BigInteger::operator+(const long long& x)const{
if(x<0){
return *this-(-x);
}
if(!flag){
return -(abs()-x);
}
BigInteger res;
res.flag=1;
res.reserve(std::max(size,x==0?0:(int(log10(x))>>3)+1)+1);
long long carry=0,n=x;
for(int i=1;n||carry;i++){
res.push(n%BASE+(i<=size?digits[i]:0)+carry);
carry=res.digits[i]/BASE;
res.digits[i]%=BASE;
n/=BASE;
}
while(res.size>1&&res.digits[res.size]==0){
res.pop();
}
return res;
}
BigInteger BigInteger::operator-(const BigInteger& x)const{
if(!x.flag){
return *this+x.abs();
}
if(!flag){
return -(abs()+x);
}
BigInteger res;
if(*this<x){
res.flag=0;
}else{
res.flag=1;
}
long long carry=0;
int n=std::max(size,x.size);
res.reserve(n);
for(int i=1;i<=n;i++){
long long d1=i<=size?digits[i]:0,d2=i<=x.size?x.digits[i]:0;
res.push(d1-d2-carry);
if(res.digits[i]<0){
res.digits[i]+=BASE;
carry=1;
}else{
carry=0;
}
}
while(res.size>1&&res.digits[res.size]==0){
res.pop();
}
return res;
}
BigInteger BigInteger::operator-(const long long& x)const{
if(x<0){
return *this+(-x);
}
if(!flag){
return -(abs()+x);
}
BigInteger res;
res.flag=1;
res.reserve(std::max(size,(int(log10(x))>>3)+1));
long long carry=0,n=x;
for(int i=1;n||carry;i++){
res.push(n%BASE-digits[i]-carry);
if(res.digits[i]<0){
res.digits[i]+=BASE;
carry=1;
}else{
carry=0;
}
n/=BASE;
}
while(res.size>1&&res.digits[res.size]==0){
res.pop();
}
return res;
}
namespace FastFourierTransformation{
constexpr long long FFT_BASE=1e4;
constexpr double PI2=6.283185307179586231995927;
constexpr double PI6=18.84955592153875869598778;
constexpr int RECALC_WIDTH=10;
constexpr int RECALC_BASE=(1<<RECALC_WIDTH)-1;
struct complex{
double real,imag;
complex(double x=0.0,double y=0.0):real(x),imag(y){}
complex operator+(const complex&other)const{
return complex(real+other.real,imag+other.imag);
}
complex operator-(const complex&other)const{
return complex(real-other.real,imag-other.imag);
}
complex operator*(const complex&other)const{
return complex(real*other.real-imag*other.imag,real*other.imag+other.real*imag);
}
complex&operator+=(const complex&other){
return real+=other.real,imag+=other.imag,*this;
}
complex&operator-=(const complex&other){
return real-=other.real,imag-=other.imag,*this;
}
complex&operator*=(const complex&other){
return *this=*this*other;
}
};
complex *arr=nullptr;
inline void init(int n){
delete[] arr;
arr=new(std::nothrow)complex[n+1];
if(!arr){
throw std::bad_alloc();
}
}
template<const int n> inline void fft(complex*a){
const int n2=n>>1,n4=n>>2;
complex w(1.0,0.0),w3(1.0,0.0);
const complex wn(cos(PI2/n),sin(PI2/n)),wn3(cos(PI6/n),sin(PI6/n));
for(int i=0;i<n4;i++,w*=wn,w3*=wn3){
if(!(i&RECALC_BASE)){
w=complex(cos(PI2*i/n),sin(PI2*i/n)),w3=w*w*w;
}
complex x=a[i]-a[i+n2],y=a[i+n4]-a[i+n2+n4];
y=complex(y.imag,-y.real);
a[i]+=a[i+n2];
a[i+n4]+=a[i+n2+n4];
a[i+n2]=(x-y)*w;
a[i+n2+n4]=(x+y)*w3;
}
fft<n2>(a);
fft<n4>(a+n2);
fft<n4>(a+n2+n4);
}
template<> inline void fft<0>(complex*){}
template<> inline void fft<1>(complex*){}
template<> inline void fft<2>(complex*a){
complex x=a[0],y=a[1];
a[0]+=y;
a[1]=x-y;
}
template<> inline void fft<4>(complex*a){
complex a0=a[0],a1=a[1],a2=a[2],a3=a[3];
complex x=a0-a2,y=a1-a3;
y=complex(y.imag,-y.real);
a[0]+=a2;
a[1]+=a3;
a[2]=x-y;
a[3]=x+y;
fft<2>(a);
}
template<const int n> inline void ifft(complex*a){
const int n2=n>>1,n4=n>>2;
ifft<n2>(a);
ifft<n4>(a+n2);
ifft<n4>(a+n2+n4);
complex w(1.0,0.0),w3(1.0,0.0);
const complex wn(cos(PI2/n),-sin(PI2/n)),wn3(cos(PI6/n),-sin(PI6/n));
for(int i=0;i<n4;i++,w*=wn,w3*=wn3){
if(!(i&RECALC_BASE)){
w=complex(cos(PI2*i/n),-sin(PI2*i/n)),w3=w*w*w;
}
complex p=w*a[i+n2],q=w3*a[i+n2+n4];
complex x=a[i],y=p+q,x1=a[i+n4],y1=p-q;
y1=complex(y1.imag,-y1.real);
a[i]+=y;
a[i+n4]+=y1;
a[i+n2]=x-y;
a[i+n2+n4]=x1-y1;
}
}
template<> inline void ifft<0>(complex*){}
template<> inline void ifft<1>(complex*){}
template<> inline void ifft<2>(complex*a){
complex x=a[0],y=a[1];
a[0]+=y;
a[1]=x-y;
}
template<> inline void ifft<4>(complex*a){
ifft<2>(a);
complex p=a[2],q=a[3];
complex x=a[0],y=p+q,x1=a[1],y1=p-q;
y1=complex(y1.imag,-y1.real);
a[0]+=y;
a[1]+=y1;
a[2]=x-y;
a[3]=x1-y1;
}
inline void dft(complex*a,int n){
if(n<=1){
return;
}
switch(n){
case 1<<2:
fft<1<<2>(a);
break;
case 1<<3:
fft<1<<3>(a);
break;
case 1<<4:
fft<1<<4>(a);
break;
case 1<<5:
fft<1<<5>(a);
break;
case 1<<6:
fft<1<<6>(a);
break;
case 1<<7:
fft<1<<7>(a);
break;
case 1<<8:
fft<1<<8>(a);
break;
case 1<<9:
fft<1<<9>(a);
break;
case 1<<10:
fft<1<<10>(a);
break;
case 1<<11:
fft<1<<11>(a);
break;
case 1<<12:
fft<1<<12>(a);
break;
case 1<<13:
fft<1<<13>(a);
break;
case 1<<14:
fft<1<<14>(a);
break;
case 1<<15:
fft<1<<15>(a);
break;
case 1<<16:
fft<1<<16>(a);
break;
case 1<<17:
fft<1<<17>(a);
break;
case 1<<18:
fft<1<<18>(a);
break;
case 1<<19:
fft<1<<19>(a);
break;
case 1<<20:
fft<1<<20>(a);
break;
case 1<<21:
fft<1<<21>(a);
break;
case 1<<22:
fft<1<<22>(a);
break;
case 1<<23:
fft<1<<23>(a);
break;
case 1<<24:
fft<1<<24>(a);
break;
case 1<<25:
fft<1<<25>(a);
break;
case 1<<26:
fft<1<<26>(a);
break;
case 1<<27:
fft<1<<27>(a);
break;
case 1<<28:
fft<1<<28>(a);
break;
throw FFTLimitExceededError();
}
}
inline void idft(complex*a,int n){
if(n<=1){
return;
}
switch(n){
case 1<<2:
ifft<1<<2>(a);
break;
case 1<<3:
ifft<1<<3>(a);
break;
case 1<<4:
ifft<1<<4>(a);
break;
case 1<<5:
ifft<1<<5>(a);
break;
case 1<<6:
ifft<1<<6>(a);
break;
case 1<<7:
ifft<1<<7>(a);
break;
case 1<<8:
ifft<1<<8>(a);
break;
case 1<<9:
ifft<1<<9>(a);
break;
case 1<<10:
ifft<1<<10>(a);
break;
case 1<<11:
ifft<1<<11>(a);
break;
case 1<<12:
ifft<1<<12>(a);
break;
case 1<<13:
ifft<1<<13>(a);
break;
case 1<<14:
ifft<1<<14>(a);
break;
case 1<<15:
ifft<1<<15>(a);
break;
case 1<<16:
ifft<1<<16>(a);
break;
case 1<<17:
ifft<1<<17>(a);
break;
case 1<<18:
ifft<1<<18>(a);
break;
case 1<<19:
ifft<1<<19>(a);
break;
case 1<<20:
ifft<1<<20>(a);
break;
case 1<<21:
ifft<1<<21>(a);
break;
case 1<<22:
ifft<1<<22>(a);
break;
case 1<<23:
ifft<1<<23>(a);
break;
case 1<<24:
ifft<1<<24>(a);
break;
case 1<<25:
ifft<1<<25>(a);
break;
case 1<<26:
ifft<1<<26>(a);
break;
case 1<<27:
ifft<1<<27>(a);
break;
case 1<<28:
ifft<1<<28>(a);
break;
throw FFTLimitExceededError();
}
}
}
BigInteger BigInteger::fft_mul(const BigInteger& a,const BigInteger& b){
int least=(a.size+b.size)<<1,lim=1<<std::__lg(least);
if(lim<least){
lim<<=1;
}
FastFourierTransformation::init(lim);
for(int i=0;i<a.size;i++){
FastFourierTransformation::arr[i<<1].real=a.digits[i+1]%FastFourierTransformation::FFT_BASE;
FastFourierTransformation::arr[i<<1 |1].real=a.digits[i+1]/FastFourierTransformation::FFT_BASE%FastFourierTransformation::FFT_BASE;
}
for(int i=0;i<b.size;i++){
FastFourierTransformation::arr[i<<1].imag=b.digits[i+1]%FastFourierTransformation::FFT_BASE;
FastFourierTransformation::arr[i<<1 |1].imag=b.digits[i+1]/FastFourierTransformation::FFT_BASE%FastFourierTransformation::FFT_BASE;
}
dft(FastFourierTransformation::arr,lim);
for(int i=0;i<lim;i++){
FastFourierTransformation::arr[i]*=FastFourierTransformation::arr[i];
}
idft(FastFourierTransformation::arr,lim);
BigInteger res;
res.resize(a.size+b.size+1);
long long carry=0;
double inv=0.5/lim;
for(int i=0;i<=a.size+b.size;i++){
carry+=(long long)(FastFourierTransformation::arr[i<<1].imag*inv+0.5);
carry+=(long long)(FastFourierTransformation::arr[i<<1 |1].imag*inv+0.5)*FastFourierTransformation::FFT_BASE;
res.digits[i+1]+=carry%BASE;
carry/=BASE;
}
while(res.size>1&&res.digits[res.size]==0){
res.pop();
}
return res;
}
BigInteger BigInteger::operator*(const BigInteger& x)const{
BigInteger zero=0;
if(*this==zero||x==zero){
return zero;
}
int n=size,m=x.size;
long long lim=1LL*n*m;
if(lim>=FFT_LIMIT){
BigInteger res=fft_mul(*this,x);
res.flag=!(flag ^x.flag);
return res;
}
BigInteger res;
res.flag=!(flag ^x.flag);
res.resize(n+m+2);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
res.digits[i+j-1]+=digits[i]*x.digits[j];
res.digits[i+j]+=res.digits[i+j-1]/BASE;
res.digits[i+j-1]%=BASE;
}
}
for(int i=1;i<=n+m+1;i++){
res.digits[i+1]+=res.digits[i]/BASE;
res.digits[i]%=BASE;
}
while(res.size>1&&res.digits[res.size]==0){
res.pop();
}
return res;
}
BigInteger BigInteger::operator*(const long long& x)const{
BigInteger t=*this;
return t*=x;
}
BigInteger BigInteger::div2()const{
BigInteger res=*this;
for(int i=size;i>=1;i--){
if((res.digits[i]&1)&&(i>1)){
res.digits[i-1]+=BASE;
}
res.digits[i]>>=1;
}
while(res.size>1&&res.digits[res.size]==0){
res.pop();
}
return res;
}
BigInteger BigInteger::operator/(const long long& x)const{
if(x==0){
throw ZeroDivisionError();
}
if(*this==0){
return 0;
}
if(x==2){
return div2();
}
if(x==-2){
return-div2();
}
BigInteger res;
res.flag=!(flag ^(x>=0));
long long cur=0,div=std::abs(x);
res.resize(size);
for(int i=size;i>=1;i--){
cur=cur*BASE+digits[i];
res.digits[i]=res.flag?(cur/div):(-cur/-div);
cur%=div;
}
while(res.size>1&&res.digits[res.size]==0){
res.pop();
}
return res;
}
inline BigInteger BigInteger::_move_r(int d)const{
if(*this==0||d>=size){
return 0;
}
if(d==0){
return *this;
}
BigInteger res;
res.reserve(size-d+1);
for(int i=d+1;i<=size;i++){
res.push(digits[i]);
}
return res;
}
inline BigInteger BigInteger::_move_l(int d)const{
if(*this==0){
return 0;
}
if(d==0){
return *this;
}
BigInteger res;
res.reserve(size+d+1);
for(int i=1;i<=d;i++){
res.push(0);
}
for(int i=1;i<=size;i++){
res.push(digits[i]);
}
return res;
}
BigInteger BigInteger::newton_inv(int n)const{
if(*this==0){
throw ZeroDivisionError();
}
if(std::min(size,n-size)<=NEWTON_DIV_MIN_LEVEL){
BigInteger a;
a.resize(n+1);
memset(a.digits,0,sizeof(long long)*a.size);
a.digits[n+1]=1;
return a.divmod(*this,1).first;
}
int k=(n-size+2)>>1,k2=k>size?0:size-k;
BigInteger x=_move_r(k2);
int n2=k+x.size;
BigInteger y=x.newton_inv(n2),a=y+y,b=(*this)*y*y;
return a._move_l(n-n2-k2)-b._move_r(2*(n2+k2)-n)-1;
}
std::pair<BigInteger,BigInteger> BigInteger::newton_div(const BigInteger& x)const{
int k=size-x.size+2,k2=k>x.size?0:x.size-k;
BigInteger x2=x._move_r(k2);
if(k2!=0){
x2+=1;
}
int n2=k+x2.size;
BigInteger u=(*this)*x2.newton_inv(n2);
BigInteger q=u._move_r(n2+k2),r=(*this)-q*x;
while(r>=x){
q+=1;
r-=x;
}
return{q,r};
}
std::pair<BigInteger,BigInteger> BigInteger::divmod(const BigInteger& x,bool dis_newton)const{
static const int base=BigInteger::BASE;
BigInteger a=abs(),b=x.abs();
if(b==0){
throw ZeroDivisionError();
}
if(a<b){
return{0,flag?a:-a};
}
if(!dis_newton&&size>NEWTON_DIV_LIMIT){
return newton_div(x);
}
int t=base/(x.digits[x.size]+1);
a*=t;
b*=t;
int n=a.size,m=b.size;
BigInteger q=0,r=0;
q.resize(n);
for(int i=n;i>=1;i--){
r*=base,r+=a.digits[i];
long long d1=m<r.size?r.digits[m+1]:0,d2=m-1<r.size?r.digits[m]:0;
int d=(d1*base+d2)/b.digits[m];
r-=b*d;
while(!r.flag){
r+=b;
d--;
}
q.digits[i]=d;
}
q.flag=!(flag ^x.flag),r.flag=flag;
while(q.size>1&&q.digits[q.size]==0){
q.pop();
}
return{q,r/t};
}
BigInteger BigInteger::operator/(const BigInteger& x)const{
return divmod(x).first;
}
BigInteger BigInteger::operator%(const long long& x)const{
if(x==2||x==4||x==5){
return digits[1]%x;
}
return*this-(*this/x*x);
}
BigInteger BigInteger::operator%(const BigInteger& x)const{
return divmod(x).second;
}
BigInteger BigInteger::pow(const long long& x)const{
BigInteger res=1,a=*this;
for(long long t=x;t!=0;t>>=1){
if(t&1){
res=res*a;
}
a=a*a;
}
return res;
}
template<typename T> BigInteger BigInteger::pow(const long long& x,const T&p)const{
BigInteger res=1,a=*this%p;
for(long long t=x;t!=0;t>>=1){
if(t&1){
res=res*a%p;
}
a=a*a%p;
}
return res;
}
BigInteger BigInteger::root(const long long& m)const{
if(!flag&&m%2==0){
throw NegativeRadicandError();
}
if(m==1||*this==0){
return *this;
}
if(m==2){
return sqrt();
}
static constexpr long long base=BigInteger::BASE;
if(size<=m){
long long l=0,r=base-1;
while(l<r){
long long mid=(l+r+1)>>1;
if(BigInteger(mid).pow(m)<=*this){
l=mid;
}else{
r=mid-1;
}
}
return l;
}
if(size<=m*2){
BigInteger res;
res.resize(2);
long long l=0,r=base-1;
while(l<r){
long long mid=(l+r+1)>>1;
res.digits[2]=mid;
if(res.pow(m)<=*this){
l=mid;
}else{
r=mid-1;
}
}
res.digits[2]=l,l=0,r=base-1;
while(l<r){
long long mid=(l+r+1)>>1;
res.digits[1]=mid;
if(res.pow(m)<=*this){
l=mid;
}else{
r=mid-1;
}
}
return res.digits[1]=l,res;
}
int n=size,t=n/m/2;
BigInteger s=(_move_r(t*m).root(m)+1)._move_l(t);
BigInteger res=(s*(m-1)+*this/s.pow(m-1))/m;
long long l=std::max<long long>(res.digits[1]-100,0),r=std::min(res.digits[1]+100,base-1);
while(l<r){
long long mid=(l+r+1)>>1;
res.digits[1]=mid;
if(res.pow(m)<=*this){
l=mid;
}else{
r=mid-1;
}
}
return res.digits[1]=l,res;
}
BigInteger BigInteger::newton_invsqrt()const{
const BigInteger& x=*this;
static constexpr long long base=BigInteger::BASE;
if(x.size<=2){
if(x.size==0){
return 0;
}
uint64_t t=0;
if(x.size==1){
t=x.digits[1];
}else{
t=x.digits[1]+x.digits[2]*BASE;
}
return uint64_t(base*base/std::sqrt(t));
}
if(x.size<=NEWTON_SQRT_MIN_LEVEL){
BigInteger b1=BigInteger(base).pow(x.size/2);
return b1/x.sqrt_normal();
}
int n2=x.size%2==0?x.size:x.size+1,k2=(n2+2)/4*2;
BigInteger x2k(x.digits+1+(n2-k2),k2+x.size-n2);
BigInteger s=x2k.newton_invsqrt()._move_l((n2-k2)/2);
BigInteger x2=(s*3).div2()-(s*s*s*x).div2()._move_r(2*n2);
BigInteger rx=BigInteger(1)._move_l(2*n2)-x*x2*x2,delta=1;
if(!rx.flag){
for(;!rx.flag;delta*=2){
BigInteger t=(x2*2-delta+delta*delta)*x;
x2-=delta;
rx+=t;
}
}else{
while(1){
BigInteger t=(x2*2+delta)*delta*x;
if(t>rx){
break;
}
x2+=delta;
rx-=t;
delta*=2;
}
}
for(;delta>0;delta=delta.div2()){
BigInteger t=(x2*2+delta)*delta*x;
if(t<=rx){
x2+=delta;
rx-=t;
}
}
return x2;
}
BigInteger BigInteger::sqrt_normal()const{
static constexpr long long base=BigInteger::BASE;
BigInteger n=*this,x0=BigInteger(base)._move_l((n.size+2)>>1);
BigInteger x=(x0+n/x0).div2();
while(x<x0){
std::swap(x,x0);
x=(x0+n/x0).div2();
}
return x0;
}
BigInteger BigInteger::sqrt()const{
if(!flag){
throw NegativeRadicandError();
}
if(*this<=1){
return *this;
}
if(size<=NEWTON_SQRT_LIMIT){
return sqrt_normal();
}
const BigInteger& x=*this;
int n2=x.size%2==0?x.size:x.size+1;
BigInteger res=(x*x.newton_invsqrt())._move_r(n2);
BigInteger r=x-res*res,delta=1;
while(1){
BigInteger dr=(res*2+delta)*delta;
if(dr>r){
break;
}
r-=dr;
res+=delta;
delta*=2;
}
for(;delta>0;delta=delta.div2()){
BigInteger dr=(res*2+delta)*delta;
if(dr<=r){
r-=dr,res+=delta;
}
}
return res;
}
BigInteger BigInteger::gcd(const BigInteger& x)const{
BigInteger a=*this,b=x;
if(a<b){
std::swap(a,b);
}
if(b==0){
return a;
}
int t=0;
while(a%2==0&&b%2==0){
a=a.div2(),b=b.div2(),t++;
}
while(b>0){
if(a%2==0){
a=a.div2();
}else if(b%2==0){
b=b.div2();
}else{
a-=b;
}
if(a<b){
std::swap(a,b);
}
}
while(t--){
a+=a;
}
return a;
}
BigInteger BigInteger::lcm(const BigInteger& x)const{
return*this/gcd(x)*x;
}
BigInteger& BigInteger::operator+=(const long long& x){
return *this=*this+x;
}
BigInteger& BigInteger::operator+=(const BigInteger& x){
return *this=*this+x;
}
BigInteger& BigInteger::operator-=(const long long& x){
return *this=*this-x;
}
BigInteger& BigInteger::operator-=(const BigInteger& x){
return *this=*this-x;
}
BigInteger& BigInteger::operator*=(long long x){
if(x==0||*this==0){
return *this=0ll;
}
if(x<0){
flag=!flag,x=-x;
}
long long carry=0;
for(int i=1;i<=size||carry;i++){
if(i>size){
push(0);
}
long long cur=digits[i]*x+carry;
carry=cur/BigInteger::BASE;
digits[i]=cur%BigInteger::BASE;
}
while(size>1&&digits[size]==0){
pop();
}
return *this;
}
BigInteger& BigInteger::operator*=(const BigInteger& x){
return *this=*this*x;
}
BigInteger& BigInteger::operator/=(const long long& x){
return *this=*this/x;
}
BigInteger& BigInteger::operator/=(const BigInteger& x){
return *this=*this/x;
}
BigInteger& BigInteger::operator%=(const long long& x){
return *this=*this%x;
}
BigInteger& BigInteger::operator%=(const BigInteger& x){
return *this=*this%x;
}
BigInteger BigInteger::operator<<(const long long& x){
return *this*BigInteger(2).pow(x);
}
BigInteger BigInteger::operator>>(const long long& x){
return *this/BigInteger(2).pow(x);
}
BigInteger& BigInteger::operator<<=(const long long& x){
return *this=*this<<x;
}
BigInteger& BigInteger::operator>>=(const long long& x){
return *this=*this>>x;
}
BigInteger BigInteger::operator&(const BigInteger& x){
std::vector<bool> a=to_binary(),b=x.to_binary();
int n=a.size(),m=b.size(),lim=std::max(n,m);
std::vector<bool> res(lim),temp(lim);
if(m==lim){
a.resize(lim);
for(int i=0;i<n;++i){
temp[lim-n+i]=a[i];
}
a=temp;
}else{
b.resize(lim);
for(int i=0;i<m;++i){
temp[lim-m+i]=b[i];
}
b=temp;
}
for(int i=0;i<lim;++i){
res[i]=a[i]&b[i];
}
return res;
}
BigInteger BigInteger::operator|(const BigInteger& x){
std::vector<bool> a=to_binary(),b=x.to_binary();
int n=a.size(),m=b.size(),lim=std::max(n,m);
std::vector<bool> res(lim),temp(lim);
if(m==lim){
a.resize(lim);
for(int i=0;i<n;++i){
temp[lim-n+i]=a[i];
}
a=temp;
}else{
b.resize(lim);
for(int i=0;i<m;++i){
temp[lim-m+i]=b[i];
}
b=temp;
}
for(int i=0;i<lim;++i){
res[i]=a[i] |b[i];
}
return res;
}
BigInteger BigInteger::operator^(const BigInteger& x){
std::vector<bool> a=to_binary(),b=x.to_binary();
int n=a.size(),m=b.size(),lim=std::max(n,m);
std::vector<bool> res(lim),temp(lim);
if(m==lim){
a.resize(lim);
for(int i=0;i<n;++i){
temp[lim-n+i]=a[i];
}
a=temp;
}else{
b.resize(lim);
for(int i=0;i<m;++i){
temp[lim-m+i]=b[i];
}
b=temp;
}
for(int i=0;i<lim;++i){
res[i]=a[i] ^b[i];
}
return res;
}
BigInteger& BigInteger::operator&=(const BigInteger& x){
return *this=*this&x;
}
BigInteger& BigInteger::operator|=(const BigInteger& x){
return *this=*this|x;
}
BigInteger& BigInteger::operator^=(const BigInteger& x){
return *this=*this^x;
}
BigInteger& BigInteger::operator++(){
return *this+=1;
}
BigInteger BigInteger::operator++(int){
BigInteger t=*this;
return *this+=1,t;
}
BigInteger& BigInteger::operator--(){
return *this-=1;
}
BigInteger BigInteger::operator--(int){
BigInteger t=*this;return *this-=1,t;
}
BigInteger BigInteger::random(const int&num_digits){
std::random_device rd;
std::mt19937 gen(rd());
BigInteger res;
res.reserve(num_digits/8+8);
res.size=0;
std::uniform_int_distribution<long long> last_digits(1,std::pow(10,(num_digits-1)%8+1)-1);
if(num_digits%8){
res.push(last_digits(gen));
}
std::uniform_int_distribution<long long> other_digits(0,99999999);
for(int i=1;i<=num_digits/8;++i){
res.push(other_digits(gen));
}
return res;
}
```