block1

back

IO优化

关闭输入输出流同步(调试时注释掉)

#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

输入优化 //read(n);

template<class T>inline void read(T &x){x=0;int f=0;char ch=getchar();while(ch<'0'||ch>'9')  {f|=(ch=='-');ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}x=f?-x:x;return;}

更快的输入优化 //用法:把上面的getchar换成这个get
注意,只能读取纯数字输入,一旦用getc,getchar和scanf都不能再使用

inline char getc(){static char buf[N],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin)),p1==p2?EOF:*p1++;}

输出优化 //write(n);

template<class T>inline void write(T x){if(x<0){putchar('-'); x=-x;}if(x>9) write(x/10);putchar(x%10+'0');}

数据结构

· 单调栈

详解
例题

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const int M=8e5+7;
struct node{
	int v,x;
}t[M];
int a[M],n,cnt,pre[M],now;
LL ans;

int main(){
	cin>>n;
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	t[++cnt].v=a[1];t[cnt].x=1;pre[1]=cnt;
	int i=2;now=1;
	while(i<=n){
		while(a[i]>=t[cnt].v&&cnt>=1){
			ans+=now-pre[t[cnt].x];
			cnt--;
		}
		t[++cnt].v=a[i];
		pre[i]=++now;
		t[cnt].x=i++;
	}
	while(cnt){
		ans+=now-pre[t[cnt--].x];
	}
	cout<<ans;
}

· 单调队列

详解
例题1
例题2

//例题1
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int M=1e6+7;
struct node{
	int v,id;
}q[M];
int h,t,n,k,a[M],ans[M],cnt;

int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	h=1;t=0;		//小 
	for(int i=1;i<=n;i++){
		while(h<=t&&i-q[h].id+1>k)h++;
		while(h<=t&&a[i]<=q[h].v)h++;
		while(h<=t&&a[i]<=q[t].v)t--;
		q[++t].v=a[i];q[t].id=i;
		if(i>=k)ans[++cnt]=q[h].v;
	}
	for(int i=1;i<=cnt;i++)cout<<ans[i]<<" ";cout<<endl;
	h=1;t=0;cnt=0;	//大 
	for(int i=1;i<=n;i++){
		while(i-q[h].id+1>k)h++;
		while(h<=t&&a[i]>=q[h].v)h++;
		while(h<=t&&a[i]>=q[t].v)t--;
		q[++t].v=a[i];q[t].id=i;
		if(i>=k)ans[++cnt]=q[h].v;
	}
	for(int i=1;i<=cnt;i++)cout<<ans[i]<<" ";
}
//例题2
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int M=2e6+7;
int h,t,k,all;
struct node{
	int v,id;
}q[M];
int main(){
	cin>>all;
	char c[10];
	int x;
	while(all--){				 //多组数据 
		h=1;t=0;k=0;int now=0;   //h队首,t队尾,k前面结束面试的人数,now面试人数统计 
		while(scanf("%s",c),c[0]!='E'){  //E为END 
			if(c[0]=='S')continue;else		 //S为START 
			if(c[0]=='C'){				 //C为加入一个来面试的人 
				scanf("%s%d",c,&x);
				now++;					 //计数器+1 
				while(h<=t&&q[h].v<=x)h++;  //队首可维护性比x低的出队 
				while(h<=t&&q[t].v<=x)t--;  //队尾可维护性比x低的出队 
				q[++t].v=x;q[t].id=now;		// x入队,id记录入队的次序 
			}else
			if(c[0]=='G'){				//G尾排在前面的人结束面试离开 
				if(k<now)k++;			//计数 
				while(h<=t&&q[h].id<=k)h++;//如果队首入队的次序小于等于k,那么他就是结束面试离开了 
			}else
			if(c[0]=='Q'){				//Q为询问最大 
				if(h<=t)printf("%d\n",q[h]);//队列不为空 
				else printf("-1\n");	//队列为空 
			}else continue;
		}
	}
}

· ST表

静态RMQ,O(nlogn)建表,O(1)查询

const int N=100007;
int a[N],st[N][20];
void st_init(){//初始化
	for(int i=1;i<=n;i++)st[i][0]=a[i];
	for(int j=1;(1<<j)<=n;j++)
	for(int i=1;i+(1<<j)-1<=n;i++)
		st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
int st_query(int l,int r){//查询
	int k=log2(r-l+1);
	return max(st[l][k],st[r-(1<<k)+1][k]);
}

· 树状数组

相对于线段树的优点:省空间,常数小,速度快

const int N=1e5+7;
int n,a[N],c[N]; //对应原数组和树状数组
int lowbit(int x){return x&(-x);}
void add(int i,int k){while(i <= n){c[i] += k;i += lowbit(i);}}
int getsum(int i){int ans = 0;while(i > 0){ans += c[i];i -= lowbit(i);}return ans;}

· 线段树

模板题

//区间修改、区间求和
const int M=1e5+7;
int t[M*4],lazy[M*4],n;//存树和lazy的数组要开4倍的MAXN
void push_up(int k){	//状态往上更新合并
	t[k]=t[k<<1]+t[k<<1|1];
}
void push_down(int k,int l,int r){	//下放lazy标记
	if(lazy[k]==0)return;
	int m=(l+r)>>1;
	lazy[k<<1]=lazy[k<<1|1]=lazy[k];
	t[k<<1]=(m-l+1)*lazy[k];
	t[k<<1|1]=(r-m)*lazy[k];
	lazy[k]=0;
}

void build(int l,int r,int k){	//建树
	if(l==r){
		t[k]=1;
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,k<<1);
	build(mid+1,r,k<<1|1);
	push_up(k);
}
void modify(int l_,int r_,int l,int r,int k,int val){ //区间修改成val
	if(l_<=l&&r_>=r){
		lazy[k]=val;
		t[k]=(r-l+1)*val;
		return;
	}
	int mid=(l+r)>>1;
	push_down(k,l,r);
	if(l_<=mid)modify(l_,r_,l,mid,k<<1,val);
	if(r_>mid)modify(l_,r_,mid+1,r,k<<1|1,val);
	push_up(k);
}
int query(int l_,int r_,int l,int r,int k){	//区间查询
	if(l_<=l&&r_>=r)return t[k];
	int mid=(l+r)>>1;
	push_down(k,l,r);
	int s=0;
	if(l_<=mid)s+=query(l_,r_,l,mid,k<<1);
	if(r_>mid)s+=query(l_,r_,mid+1,r,k<<1|1);
	return s;
}

区间加减、区间乘法、区间求和
模板题

//乘法标记时,把当前点的加法标记也乘上val。push_down操作时先乘后加,因为加法是已经乘了乘法标记的
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+7;
typedef long long LL;

LL n,m,a[MAXN];
LL t[MAXN*4],lazy[MAXN*4],p,lazy2[MAXN*4];//lazy是加法懒标记,lazy2是乘法懒标记
template<class T>void read(T &x){x=0;int f=0;char ch=getchar();while(ch<'0'||ch>'9')  {f|=(ch=='-');ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}x=f?-x:x;return;}//快读
void push_up(int k){
	t[k]=(t[k<<1]+t[k<<1|1])%p;
}
void push_plus(int k,int l,int r){
	if(l==r||lazy[k]==0)return;
	lazy[k<<1]=(lazy[k<<1]+lazy[k])%p;
	lazy[k<<1|1]=(lazy[k<<1|1]+lazy[k])%p;
	int md=(l+r)>>1;
	t[k<<1]=(t[k<<1]+lazy[k]*(md-l+1)%p)%p;
	t[k<<1|1]=(t[k<<1|1]+lazy[k]*(r-md)%p)%p;
	lazy[k]=0;
}//下放加法懒标记	
void push_multi(int k,int l,int r){
	if(l==r||lazy2[k]==1)return;
	lazy[k<<1]=lazy[k<<1]*lazy2[k]%p;
	lazy[k<<1|1]=lazy[k<<1|1]*lazy2[k]%p;
	lazy2[k<<1]=lazy2[k<<1]*lazy2[k]%p;
	lazy2[k<<1|1]=lazy2[k<<1|1]*lazy2[k]%p;
	int md=(l+r)>>1;
	t[k<<1]=t[k<<1]*lazy2[k]%p;
	t[k<<1|1]=t[k<<1|1]*lazy2[k]%p;
	lazy2[k]=1;
}//下放乘法懒标记(对应点的加法懒标记同时也乘上val)

void build(int l,int r,int k){
	if(l==r){
		t[k]=a[l]%p;
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,k<<1);
	build(mid+1,r,k<<1|1);
	push_up(k);
}//建树
void updata_plus(int l_,int r_,int l,int r,int k,int val){
	if(l_<=l&&r_>=r){
		lazy[k]=(lazy[k]+val)%p;
		t[k]=(t[k]+(r-l+1)*val%p)%p;
		return;
	}
	int mid=(l+r)>>1;
	push_multi(k,l,r);
	push_plus(k,l,r);//先乘后加
	if(l_<=mid)updata_plus(l_,r_,l,mid,k<<1,val);
	if(r_>mid)updata_plus(l_,r_,mid+1,r,k<<1|1,val);
	push_up(k);
}//区间加减
void updata_multi(int l_,int r_,int l,int r,int k,int val){
	if(l_<=l&&r_>=r){
		lazy[k]=lazy[k]*val%p;//加法标记同时也乘val
		lazy2[k]=lazy2[k]*val%p;
		t[k]=t[k]*val%p;
		return;
	}
	int mid=(l+r)>>1;
	push_multi(k,l,r);
	push_plus(k,l,r);
	if(l_<=mid)updata_multi(l_,r_,l,mid,k<<1,val);
	if(r_>mid)updata_multi(l_,r_,mid+1,r,k<<1|1,val);
	push_up(k);
}//区间乘法
LL query(int l_,int r_,int l,int r,int k){
	if(l_<=l&&r_>=r)return t[k]%p;
	int mid=(l+r)>>1;
	LL sum=0;
	push_multi(k,l,r);
	push_plus(k,l,r);
	if(l_<=mid)sum=(sum+query(l_,r_,l,mid,k<<1))%p;
	if(r_>mid)sum=(sum+query(l_,r_,mid+1,r,k<<1|1))%p;
	return sum;
}
int main(){
	cin>>n>>m>>p;
	for(int i=1;i<=n;i++)read(a[i]);
	for(int i=1;i<=MAXN*4-1;i++)lazy2[i]=1;
	build(1,n,1);
	int b,c,d,e;
	for(int i=1;i<=m;i++){
		 read(b);
		 if(b==1){//乘法
		 	read(c);read(d);read(e);
		 	updata_multi(c,d,1,n,1,e);
		 }else
		 if(b==2){//加法
		 	read(c);read(d);read(e);
		 	updata_plus(c,d,1,n,1,e);
		 }else{//求和
		 	read(c);read(d);
		 	printf("%lld\n",query(c,d,1,n,1));
		 }
	}
}

· 分块

n √ n n√n nn

Loj分块入门1~9题
hzwer学长的详解链接我的题解链接

1.单点加减、区间加减、区间求和

const int N=1e5+7;
typedef long long ll;

int n,m,size,cnt,l[N],r[N],belong[N];
ll v[N],a[N],lazy[N];
//l,r是第i块的左右端点,belong记录i点属于哪个块
//size是块的大小,cnt是块的数量,v是块维护的值

void build(){	//划分建块 
	size=sqrt(n); 
	cnt=n/size;if(n%size)cnt++;//设定块的大小和数量 
	for(int i=1;i<=cnt;i++)		//记录每个块的左右端点 
		l[i]=(i-1)*size+1,r[i]=i*size;
	r[cnt]=n;
	for(int i=1;i<=n;i++)		//记录每个点属于哪个块 
		belong[i]=(i-1)/size+1;
	for(int i=1;i<=cnt;i++)		//初始化 
		for(int j=l[i];j<=r[i];j++)
			v[i]+=a[j];
}
inline void plus(int x,int val){//单点加val 
	a[x]+=val;
	v[belong[x]]+=val;
}
inline void add(int L,int R,ll c){//区间加val
	if(belong[L]==belong[R]){
		for(int i=L;i<=R;i++)a[i]+=c,v[belong[i]]+=c;
		return;
	}
	for(int i=L;i<=r[belong[L]];i++)a[i]+=c,v[belong[i]]+=c;
	for(int i=belong[L]+1;i<belong[R];i++)lazy[i]+=c;
	for(int i=l[belong[R]];i<=R;i++)a[i]+=c,v[belong[i]]+=c;
}
inline ll query(int L,int R,ll c){//区间求和(mod c)
	ll ans=0;
	if(belong[L]==belong[R]){
		for(int i=L;i<=R;i++)ans=(ans+a[i]+lazy[belong[i]])%c;
		return ans;
	}
	for(int i=L;i<=r[belong[L]];i++)ans=(ans+a[i]+lazy[belong[i]])%c;
	for(int i=belong[L]+1;i<belong[R];i++)ans=(ans+v[i]+lazy[i]*(r[i]-l[i]+1))%c;
	for(int i=l[belong[R]];i<=R;i++)ans=(ans+a[i]+lazy[belong[i]])%c;
	return ans;
}
//inline ll query_(int l_,int r_){//没有lazy数组的区间求和 
//	ll ans=0;
//	if(belong[l_]==belong[r_]){//在同一个块内 
//		for(int i=l_;i<=r_;i++)ans+=a[i];
//		return ans;
//	}
//	for(int i=l_;i<=r[belong[l_]];i++)
//		ans+=a[i];	//左端点非整体块暴力 
//	for(int i=belong[l_]+1;i<belong[r_];i++)
//		ans+=v[i];	//中间整体快累加 
//	for(int i=l[belong[r_]];i<=r_;i++)
//		ans+=a[i];	//右端点非整体块暴力 
//	return ans;
//}

2.区间加减、求区间内小于k的元素个数。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=50007;
template<class T>inline void read(T &x){
	x=0;int f=0;char ch=getchar();
	while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	x=f?-x:x;
	return;
}
int n,size,cnt,l[N],r[N],belong[N];
int a[N],lazy[N];
vector<int>vec[505];//块内排序 
void build(){
	size=sqrt(n);
	cnt=n/size;if(n%size)cnt++;
	for(int i=1;i<=cnt;i++)
		l[i]=(i-1)*size+1,r[i]=i*size;
	r[cnt]=n;
	for(int i=1;i<=n;i++){
		belong[i]=(i-1)/size+1;
		vec[belong[i]].push_back(a[i]);
	}
	for(int i=1;i<=cnt;i++)
		sort(vec[i].begin(),vec[i].end());
}
void reset(int x){//重新排序 
	vec[x].clear();
	for(int i=l[x];i<=r[x];i++)
		vec[x].push_back(a[i]);
	sort(vec[x].begin(),vec[x].end());
}
void add(int L,int R,int c){
	if(belong[L]==belong[R]){
		for(int i=L;i<=R;i++)a[i]+=c;
		reset(belong[L]);
		return;
	}
	for(int i=L;i<=r[belong[L]];i++)a[i]+=c;
	reset(belong[L]);
	for(int i=belong[L]+1;i<belong[R];i++)lazy[i]+=c;
	for(int i=l[belong[R]];i<=R;i++)a[i]+=c;
	reset(belong[R]);
}
int query(int L,int R,int c){
	int ans=0;
	if(belong[L]==belong[R]){
		for(int i=L;i<=R;i++)
			if(a[i]+lazy[belong[i]]<c)ans++;
		return ans;
	}
	for(int i=L;i<=r[belong[L]];i++)
		if(a[i]+lazy[belong[i]]<c)ans++;
	for(int i=belong[L]+1;i<belong[R];i++){
		int x=c-lazy[i];
		ans+=lower_bound(vec[i].begin(),vec[i].end(),x)-vec[i].begin();
	}
	for(int i=l[belong[R]];i<=R;i++)
		if(a[i]+lazy[belong[i]]<c)ans++;
	return ans;
}	
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)read(a[i]);
	build();
	int opt,l,r,c;
	for(int i=1;i<=n;i++){
		read(opt);read(l);read(r);read(c);
		if(opt==0)add(l,r,c);
		else printf("%d\n",query(l,r,c*c));
	}
}

· 珂朵莉树

操作随机的话复杂度接近O(mlogn)
1.必须先split(r+1),再split(l),否则可能会使split(l)的迭代器失效
2.初始化插入完节点后,要插入一个node(n+1,n+1,0)的节点

例题1(生成随机数)
题解

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
typedef long long LL;
#define IT set<node>::iterator 
const int MAXN=1e5+7;
const int MOD7=1e9+7;
struct node{
	int l,r;
	mutable LL v;
	node(int L,int R=-1,LL V=0):l(L),r(R),v(V){}
	bool operator<(const node &o)const{
		return l<o.l;
	}
};
LL qpow(LL a,LL b,LL mod){//快速幂 
	LL ans=1;
	LL x=a%mod;
	while(b){
		if(b&1)ans=ans*x%mod;
		x=x*x%mod;
		b>>=1;
	}
	return ans;
}
set<node>s;
IT split(int pos){//必须先split(r+1),再split(l)
	IT it=s.lower_bound(node(pos));
	if(it!=s.end()&&it->l==pos)return it;
	--it;
	int L=it->l,R=it->r;
	LL V=it->v;
	s.erase(it);
	s.insert(node(L,pos-1,V));
	return s.insert(node(pos,R,V)).first;
}
void add(int l,int r,LL val){//给l到r所有数加上val 
	IT itr=split(r+1),itl=split(l);
	for(;itl!=itr;++itl)
		itl->v+=val;
}
void assign_val(int l,int r,LL val){//把l到r所有数改为val 
	IT itr=split(r+1),itl=split(l);
	s.erase(itl,itr);
	s.insert(node(l,r,val));
}
LL ranks(int l,int r,int k){//询问l到r区间第k小 
	vector<pair<LL,int> >vp;
	IT itr=split(r+1),itl=split(l);
	vp.clear();
	for(;itl!=itr;++itl)
		vp.push_back(pair<LL,int>(itl->v,itl->r - itl->l +1));
	sort(vp.begin(),vp.end());
	for(vector<pair<LL,int> >::iterator it=vp.begin();it!=vp.end();++it){
		k-=it->second;
		if(k<=0)return it->first;
	}
}
LL sum(int l,int r,int ex,int mod){//询问l到r每个数字的x次方模y的和 
	IT itr=split(r+1),itl=split(l);
	LL res=0;
	for(;itl!=itr;++itl)
		res=(res+(LL)(itl->r - itl->l+1)*qpow(itl->v,LL(ex),LL(mod))) %mod;
	return res;
}
int n,m;
LL seed,vmax;
LL rd(){
	LL ret=seed;
	seed=(seed*7+13)%MOD7;
	return ret;
}
LL a[MAXN];
int main(){
	cin>>n>>m>>seed>>vmax;
	for(int i=1;i<=n;i++){
		a[i]=(rd()%vmax)+1;
		s.insert(node(i,i,a[i]));
	}
	s.insert(node(n+1,n+1,0));
	int lines=0;
	for(int i=1;i<=m;i++){
		//----------------------------- 
		int op=int(rd()%4)+1;
		int l=int(rd()%n)+1;
		int r=int(rd()%n)+1;
		if(l>r)swap(l,r);
		int x,y;
		if(op==3)x=int(rd()%(r-l+1))+1;
		else x=int(rd()%vmax)+1;
		if(op==4)y=int(rd()%vmax)+1;
		//------------------------------以上为题目要求生成数据 
		
		if(op==1)add(l,r,LL(x));
		else if(op==2)assign_val(l,r,LL(x));
		else if(op==3)cout<<ranks(l,r,x)<<endl;
		else cout<<sum(l,r,x,y)<<endl;
	}
	return 0;
}

例题2(给定每次操作)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
typedef long long LL;
#define IT set<node>::iterator 
struct node{
	int l,r;
	mutable LL v;
	node(int L,int R=-1,LL V=0):l(L),r(R),v(V){}
	bool operator<(const node &o)const{
		return l<o.l;
	}
};
LL qpow(LL a,LL b,LL mod){//快速幂 
	LL ans=1;
	LL x=a%mod;
	while(b){
		if(b&1)ans=ans*x%mod;
		x=x*x%mod;
		b>>=1;
	}
	return ans;
}
set<node>s;
IT split(int pos){
	IT it=s.lower_bound(node(pos));
	if(it!=s.end()&&it->l==pos)return it;
	--it;
	int L=it->l,R=it->r;
	LL V=it->v;
	s.erase(it);
	s.insert(node(L,pos-1,V));
	return s.insert(node(pos,R,V)).first;
}
void add(int l,int r,LL val){//给l到r所有数加上val 
	IT itr=split(r+1),itl=split(l);
	for(;itl!=itr;++itl)
		itl->v=(itl->v+val)%10007;
}
void muti(int l,int r,LL val){//给l到r所有数乘上val 
	IT itr=split(r+1),itl=split(l);
	for(;itl!=itr;++itl)
		itl->v=(itl->v*val)%10007;
}
void assign_val(int l,int r,LL val){//把l到r所有数改为val 
	IT itr=split(r+1),itl=split(l);
	s.erase(itl,itr);
	s.insert(node(l,r,val));
}
LL sum(int l,int r,int ex){//询问l到r每个数字的x次方和 
	IT itr=split(r+1),itl=split(l);
	LL res=0;
	for(;itl!=itr;++itl)
		res=(res+(long long)(itl->r - itl->l+1)*qpow(itl->v,(long long)ex,10007))%10007;
	return res;
}
int n,m;
int main(){
	while(cin>>n>>m,n!=0||m!=0){
		s.clear();
		s.insert(node(1,n,0));
		s.insert(node(n+1,n+1,0));
		int opt,x,y;
		long long z;
		for(int i=1;i<=m;i++){
			scanf("%d%d%d%lld",&opt,&x,&y,&z);
			if(opt==1)add(x,y,z);else
			if(opt==2)muti(x,y,z);else
			if(opt==3)assign_val(x,y,z);else
			printf("%lld\n",sum(x,y,z));
		}
	}
	return 0;
}

高精度

__int128的数据范围是[-1.7e38,+1.7e38],必须用IO优化输入输出,long long可以直接赋值给__int128

大数模板:加减乘除、取余、乘方、快速幂、cin,cout、比较大小、int转化

class BigNum{
	private:
		#define MAXN 9999
		#define MAXSIZE 1500
		#define DLEN 4
   		int a[MAXSIZE];    //可以控制大数的位数
    	int len;      	   //大数长度
	public:
   		BigNum(){len=1;memset(a,0,sizeof(a));}//构造函数
    	BigNum(const int);       //将一个int类型的变量转化为大数
    	BigNum(const char*);     //将一个字符串类型的变量转化为大数
    	BigNum(const BigNum &);  //拷贝构造函数
    	BigNum &operator=(const BigNum &);   //重载赋值运算符,大数之间进行赋值运算
  
   		friend istream& operator>>(istream&,  BigNum&);   //重载输入运算符
    	friend ostream& operator<<(ostream&,  BigNum&);   //重载输出运算符
  
    	BigNum operator+(const BigNum &) const;   //重载加法运算符,两个大数之间的相加运算
    	BigNum operator-(const BigNum &) const;   //重载减法运算符,两个大数之间的相减运算
    	BigNum operator*(const BigNum &) const;   //重载乘法运算符,两个大数之间的相乘运算
    	BigNum operator/(const int &) const;    //重载除法运算符,大数对一个整数进行相除运算
  
    	BigNum operator^(const int &) const;    //大数的n次方运算
    	int    operator%(const int &) const;    //大数对一个int类型的变量进行取模运算
    	bool   operator>(const BigNum &T)const;   //大数和另一个大数的大小比较
    	bool   operator>(const int &t)const;      //大数和一个int类型的变量的大小比较
  
    	void print();       //输出大数
};
BigNum BigNum_qpow(BigNum x,BigNum e);//大数快速幂 

BigNum::BigNum(const int b){//将一个int类型的变量转化为大数
    int c,d=b;
    len=0;
    memset(a,0,sizeof(a));
    while(d>MAXN){
        c=d-(d/(MAXN+1))*(MAXN+1);
        d=d/(MAXN+1);
        a[len++]=c;
    }
    a[len++]=d;
}
BigNum::BigNum(const char*s){//将一个字符串类型的变量转化为大数
    int t,k,index,l,i;
    memset(a,0,sizeof(a));
    l=strlen(s);
    len=l/DLEN;
    if(l%DLEN)len++;
    index=0;
    for(i=l-1;i>=0;i-=DLEN){
        t=0;
        k=i-DLEN+1;
        if(k<0)k=0;
        for(int j=k;j<=i;j++)t=t*10+s[j]-'0';
        a[index++]=t;
    }
}
BigNum::BigNum(const BigNum &T):len(T.len){ //拷贝构造函数
    int i;
    memset(a,0,sizeof(a));
    for(i=0;i<len;i++)a[i]=T.a[i];
}
BigNum & BigNum::operator=(const BigNum &n){//重载赋值运算符,大数之间进行赋值运算
    int i;
    len=n.len;
    memset(a,0,sizeof(a));
    for(i=0;i<len;i++)a[i]=n.a[i];
    return *this;
}
istream& operator>>(istream &in,BigNum &b){//重载输入运算符
    char ch[MAXSIZE*4];
    int i=-1;
    in>>ch;
    int l=strlen(ch);
    int count=0,sum=0;
    for(i=l-1;i>=0;){
        sum=0;
        int t=1;
        for(int j=0;j<4&&i>=0;j++,i--,t*=10){
            sum+=(ch[i]-'0')*t;
        }
        b.a[count]=sum;
        count++;
    }
    b.len=count++;
    return in;
}
ostream& operator<<(ostream &out,BigNum &b){//重载输出运算符
    int i;
    cout<<b.a[b.len-1];
    for(i=b.len-2;i>=0;i--){
        cout.width(DLEN);
        cout.fill('0');
        cout<<b.a[i];
    }
    return out;
}
BigNum BigNum::operator+(const BigNum &T)const{//两个大数之间的相加运算
    BigNum t(*this);
    int i,big;      //位数
    big=T.len>len?T.len:len;
    for(i=0;i<big;i++){
        t.a[i]+=T.a[i];
        if(t.a[i]>MAXN){
            t.a[i+1]++;
            t.a[i]-=MAXN+1;
        }
    }
    if(t.a[big]!=0)t.len=big+1;
    else t.len=big;
    return t;
}
BigNum BigNum::operator-(const BigNum &T)const{//两个大数之间的相减运算
    int i,j,big;
    bool flag;
    BigNum t1,t2;
    if(*this>T){
        t1=*this;
        t2=T;
        flag=0;
    }else{
        t1=T;
        t2=*this;
        flag=1;
    }
    big=t1.len;
    for(i=0;i<big;i++){
        if(t1.a[i]<t2.a[i]){
            j=i+1;
            while(t1.a[j]==0)j++;
            t1.a[j--]--;
            while(j > i)t1.a[j--]+=MAXN;
            t1.a[i]+=MAXN+1-t2.a[i];
        }
        else t1.a[i]-=t2.a[i];
    }
    t1.len=big;
    while(t1.a[len-1]==0&&t1.len>1){
        t1.len--;
        big--;
    }
    if(flag)t1.a[big-1]=0-t1.a[big-1];
    return t1;
}
  
BigNum BigNum::operator*(const BigNum &T)const{//两个大数之间的相乘运算
    BigNum ret;
    int i,j,up;
    int temp,temp1;
    for(i=0;i<len;i++){
        up=0;
        for(j=0;j<T.len;j++){
            temp=a[i]*T.a[j]+ret.a[i + j]+up;
            if(temp>MAXN){
                temp1=temp-temp/(MAXN+1)*(MAXN + 1);
                up=temp/(MAXN+1);
                ret.a[i+j]=temp1;
            }else{
                up=0;
                ret.a[i+j]=temp;
            }
        }
        if(up!=0)ret.a[i+j]=up;
    }
    ret.len=i+j;
    while(ret.a[ret.len-1]==0&&ret.len>1)ret.len--;
    return ret;
}
BigNum BigNum::operator/(const int &b)const{//大数对一个整数进行相除运算
    BigNum ret;
    int i,down=0;
    for(i=len-1;i>=0;i--){
        ret.a[i]=(a[i]+down*(MAXN+1))/b;
        down=a[i]+down*(MAXN+1)-ret.a[i]*b;
    }
    ret.len=len;
    while(ret.a[ret.len-1]==0&&ret.len>1)ret.len--;
    return ret;
}
int BigNum::operator %(const int &b)const{//大数对一个int类型的变量进行取模运算
    int i,d=0;
    for (i=len-1;i>=0;i--){
        d=((d*(MAXN+1))%b+a[i])%b;
    }
    return d;
}
BigNum BigNum::operator^(const int &n)const{//大数的n次方运算
    BigNum t,ret(1);
    int i;
    if(n<0)exit(-1);
    if(n==0)return 1;
    if(n==1)return *this;
    int m=n;
    while(m>1){
        t=*this;
        for(i=1;i<<1<=m;i<<=1){
            t=t*t;
        }
        m-=i;
        ret=ret*t;
        if(m==1)ret=ret*(*this);
    }
    return ret;
}
BigNum BigNum_qpow(BigNum x,BigNum e){//大数快速幂
	BigNum re(1);
	while(e>0){
		if(e%2)re=re*x;
		x=x*x;
		e=e/2;
	}
	return re;
}	
bool BigNum::operator>(const BigNum &T)const{//大数和另一个大数的大小比较
    int ln;
    if(len>T.len)return true;
    else if(len==T.len){
        ln=len-1;
        while(a[ln]==T.a[ln]&&ln>=0)ln--;
        if(ln>=0&&a[ln]>T.a[ln])return true;
        else return false;
    }
    else return false;
}
bool BigNum::operator>(const int &t)const{//大数和一个int类型的变量的大小比较
    BigNum b(t);
    return *this>b;
}		 
void BigNum::print(){//输出大数
    int i;
    cout<<a[len-1];
    for(i=len-2;i>=0;i--){
        cout.width(DLEN);
        cout.fill('0');
        cout<<a[i];
    }
    cout<<endl;
}


STL

vector

//分配大小
vector<int>a(n);
//二维vector分配大小
vector<vector<int> >d(n,vector<int>(m));

map
用pair作为unordered_map的键值,自定义hash

struct pair_hash{
    template<class T1,class T2>
    std::size_t operator()(const std::pair<T1,T2>&p)const{
        auto h1=std::hash<T1>{}(p.first);
        auto h2=std::hash<T2>{}(p.second);
        return h1^h2;
    }
};
unordered_map<pair<int, bool>, int, pair_hash>mp;
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linkscx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值