C++竞赛常用实用代码(5)

前言 

所有代码中未加的默认加上“#define ll long long”

Dinic的板子打错了好多遍,现在改过来了,非常抱歉

上一页:C++竞赛常用实用代码(4)

目录

线性筛求欧拉函数

线性筛求莫比乌斯函数

快速傅里叶变换(FFT)

快速数论变换(NTT)

快速沃尔什变换FWT(改进)

快速莫比乌斯变换(FMT)

匈牙利算法模板

最大流Dinic算法模板

二分图最大权完美匹配KM算法模板

SPFA求费用流模板

三种最小生成树算法

Kruskal(首选)

Prim(用的少)

Boruvka(高级)

浮点数高斯消元

模线性高斯消元

普通BSGS(大步小步算法)

exBSGS(扩展大步小步算法)


下一页:C++竞赛常用实用代码(6)

线性筛求欧拉函数

int ph[MAXN];
bool nop[MAXN];
vector<int>pri;//素数集
inline void getphi(int n){//套用欧拉筛
	nop[0]=nop[1]=1;
	for(int i=1;i<=n;i++)ph[i]=i;
	for(int a=2;a<=n;a++){
		if(!nop[a])pri.push_back(a),ph[a]=a-1;
		for(int i=0,u;i<pri.size()&&pri[i]*a<=n;i++){
			u=pri[i]*a,nop[u]=1;
			if(a%pri[i]==0)ph[u]=ph[a]*pri[i],i=MAXN;
			else ph[u]=ph[a]*ph[pri[i]];
		}
	}
}

线性筛求莫比乌斯函数

int mu[MAXN];
bool nop[MAXN];
vector<int>pri;//素数集
inline void getmu(int n){//套用欧拉筛
	mu[1]=1,nop[0]=nop[1]=1;
	for(int a=2;a<=n;a++){
		if(!nop[a])pri.push_back(a),mu[a]=-1;
		for(int i=0,u;i<pri.size()&&pri[i]*a<=n;i++){
			u=pri[i]*a,nop[u]=1;
			if(a%pri[i]==0)mu[u]=0,i=MAXN;
			else mu[u]=-mu[a];
		}
	}
}

快速傅里叶变换(FFT)

#define cp complex<double> //记得加上<complex>头文件
const double pi=acos(-1);
int rev[MAXN];
inline int FFT(cp*a,int N,int inv){
	int bit=0,n=N;
	while((1<<bit)<n)bit++;n=(1<<bit);//把n扩成2的次幂
	for(int i=0;i<n;i++){
		rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
		if(i<rev[i])swap(a[i],a[rev[i]]);
	}cp tmp,omega,y;
    for(int mid=1;mid<n;mid<<=1){
		tmp=cp(cos(pi/mid),inv*sin(pi/mid)),omega=cp(1,0);
		for(int i=0;i<n;i+=(mid<<1),omega=cp(1,0))
			for(int j=0;j<mid;j++,omega*=tmp)
				y=omega*a[i+j+mid],a[i+j]+=y,a[i+j+mid]=a[i+j]-y-y;
	}
    if(inv<0)for(int i=0;i<n;i++)a[i].real()/=n;//逆变换要除以n
	return n;//返回数组长度
}

快速数论变换(NTT)

#define mod 998244353ll    //模数一般为998244353
#define g 3ll    //原根
int rev[MAXN<<1];
inline ll ksm(ll a,ll b,ll mo){//快速幂
	ll res=1;
	for(;b;b>>=1,a=a*a%mo)if(b&1)res=res*a%mo;
	return res;
}
inline int NTT(ll*a,int N,int op){
	int bit=0,n=N;while((1<<bit)<n)bit++;n=(1<<bit);
	for(int i=0;i<n;i++){
		rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
		if(i<rev[i])swap(a[i],a[rev[i]]);
	}
	for(int m=1,mi=(MOD-1)/(m<<1);m<n;m<<=1,mi>>=1){
		ll tmp=op>0?ksm(g,mi,MOD):ksm(g,MOD-mi-1,MOD),om=1,y;
		for(int i=0;i<n;i+=(m<<1),om=1)
			for(int j=i;j<i+m;j++,om=om*tmp%MOD)
				y=om*a[j+m]%MOD,a[j]=(a[j]+y)%MOD,a[j+m]=(a[j]+((MOD-y)<<1))%MOD;
	}
	if(op<0){ll inv=ksm(n,MOD-2,MOD);
		for(int i=0;i<n;i++)a[i]=a[i]*inv%MOD;
	}return n;
}
#undef g

快速沃尔什变换FWT(改进)

//所有函数中传入inv=1表示正变换,-1表示逆变换
inline void FWTOR(int*a,int n,int inv){    //按位或
	for(int k=2;k<=n;k<<=1)//k的枚举从大到小和从小到大,结果是完全一样的
		for(int i=0;i<n;i+=k)
			for(int j=i;j<i+(k>>1);j++)
				a[j+(k>>1)]=(a[j+(k>>1)]+a[j]*inv+MOD)%MOD;
}

inline void FWTAND(int*a,int n,int inv){    //按位与
	for(int k=2;k<=n;k<<=1)
		for(int i=0;i<n;i+=k)
			for(int j=i;j<i+(k>>1);j++)
				a[j]=(a[j]+a[j+(k>>1)]*inv+MOD)%MOD;
}

//此处应有个快速幂
inline void FWTXOR(int*a,int n,int inv){    //异或
	ll in2=inv>0?1:ksm(2,MOD-2,MOD),a0,a1;
	for(int k=2;k<=n;k<<=1)
        for(int i=0;i<n;i+=k)
		    for(int j=i;j<i+(k>>1);j++)
			    a0=a[j],a1=a[j+(k>>1)],a[j]=(a0+a1)%MOD*in2%MOD,a[j+(k>>1)]=(a0-a1+MOD)%MOD*in2%MOD;
}

快速莫比乌斯变换(FMT)

主要用来代替FWT的按位或、与部分,用法相同

inline void FMTOR(int*a,int n,int inv){//按位或
	for(int k=1;k<n;k<<=1)
		for(int i=0;i<n;i++)
			if(~i&k)a[i|k]=(a[i|k]+a[i]*inv+MOD)%MOD;
}

inline void FMTAND(int*a,int n,int inv){//按位与
	for(int k=1;k<n;k<<=1)
		for(int i=n-1;i>=0;i--)
			if(i&k)a[i^k]=(a[i^k]+a[i]*inv+MOD)%MOD;
}

更多有关快速沃尔什变换和莫比乌斯变换

匈牙利算法模板

int mat[MAXN];
vector<int>G[MAXN];
bool vis[MAXN];

inline bool findh(int x){
	for(int i=0;i<G[x].size();i++)
		if(!vis[G[x][i]]){
			int v=G[x][i];vis[v]=1;
			if(mat[v]<0||findh(mat[v])){
				mat[v]=x;return 1;
			}
		}
	return 0;
}
inline int hungary(){
	memset(mat,-1,sizeof(mat));
	int res=0;
	for(int i=0;i<n;i++){
		memset(vis,0,sizeof(vis));
		if(findh(i))res++;
	}
	return res;
}

最大流Dinic算法模板

#define INF 0x3f3f3f3f
int d[MAXN],cur[MAXN];
ll f[MAXN];
struct edge{
	int v,id,fd;edge(){}
	edge(int V,int I,int F){v=V,id=I,fd=F;}
};
vector<edge>G[MAXN];
queue<int>q;
 
inline bool bfs(int S,int T){
	while(!q.empty())q.pop();
	memset(d,-1,sizeof(d));
	d[S]=0,q.push(S);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=0;i<G[u].size();i++)
			if(f[G[u][i].id]>0&&d[G[u][i].v]<0)
				d[G[u][i].v]=d[u]+1,q.push(G[u][i].v);
	}
	return d[T]>=0;
}
inline ll dfs(int x,ll lim,int T){
	if(x==T)return lim;
	ll res=lim;
	for(int i=cur[x];i<G[x].size()&&res>0;i++){
		cur[x]=i;
		int v=G[x][i].v,a=G[x][i].id,b=G[x][i].fd;
		if(f[a]>0&&d[v]==d[x]+1){
			int ad=dfs(v,min(res,f[a]),T);
			f[a]-=ad,f[b]+=ad,res-=ad;
		}
	}
	return lim-res;
}
inline ll dinic(int S,int T){
	ll res=0;
	while(bfs(S,T)){
		memset(cur,0,sizeof(cur));
		while(ll ad=dfs(S,INF,T))res+=ad;
	}
	return res;
}

前向星改进版:

#define ll long long
#define INF 1e17
struct edge{
	int v,to;ll f;edge(){}
	edge(int V,ll F,int T){v=V,f=F,to=T;}
}e[1000005];
int EN=1,G[MAXN],ps;
inline void addedge(int u,int v,ll f){
	e[++EN]=edge(v,f,G[u]),G[u]=EN;
	e[++EN]=edge(u,0,G[v]),G[v]=EN;
}
int cur[MAXN],ds[MAXN];
queue<int>q;
inline bool dcbfs(int S,int T){
	for(int i=1;i<=ps;i++)ds[i]=-1;
	while(!q.empty())q.pop();
	q.push(S),ds[S]=0;
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=G[u];i;i=e[i].to){
			int v=e[i].v;
			if(e[i].f>0&&ds[v]<0)ds[v]=ds[u]+1,q.push(v);
		}
	}return ds[T]>=0;
}
inline ll dcdfs(int x,int T,ll lim){
	if(x==T)return lim;
	ll res=lim;
	for(int i=cur[x];i&&res;i=e[i].to){
		cur[x]=i;
		int v=e[i].v;
		if(ds[v]==ds[x]+1&&e[i].f>0){
			ll ad=dcdfs(v,T,min(e[i].f,res));
			e[i].f-=ad,res-=ad,e[i^1].f+=ad;
		}
	}return lim-res;
}
inline ll dinic(int S,int T){
	ll res=0;
	while(dcbfs(S,T)){
		for(int i=1;i<=ps;i++)cur[i]=G[i];
		while(ll ad=dcdfs(S,T,INF))res+=ad;
	}
	return res;
}

二分图最大权完美匹配KM算法模板

递归版(O(n^4)):

int n,mat[505];
ll w[505][505],exg[505],exb[505],lak[505];
bool vg[505],vb[505];

inline bool dfs(int x){
	vg[x]=1;
	for(int v=1;v<=n;v++)
		if(!vb[v]){
			ll gap=exg[x]+exg[v]-w[x][v];
			if(gap==0){
				vb[v]=1;
				if(mat[v]<0||dfs(mat[v])){
					mat[v]=x;return 1;
				}
			}
			else lak[v]=min(lak[v],gap);
		}
	return 0;
}
inline ll KM(){
	memset(mat,-1,sizeof(mat));
	mst0(exb);
	for(int i=1;i<=n;i++){
		exg[i]=w[i][1];
		for(int j=2;j<=n;j++)
			exg[i]=max(exg[i],w[i][j]);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)lak[j]=INF;
		while(1){
			mst0(vg);mst0(vb);
			if(dfs(i))break;
			ll ad=INF;
			for(int j=1;j<=n;j++)
				if(!vb[j])ad=min(ad,lak[j]);
			for(int j=1;j<=n;j++){
				if(vg[j])exg[j]-=ad;
				if(vb[j])exb[j]+=ad;
				else lak[j]-=ad;
			}
		}
	}
	ll res=0;
	for(int i=1;i<=n;i++)res+=w[mat[i]][i]-ADD;
	return res;
}

BFS版(O(n^3)):

#define mst0(x) memset(x,0,sizeof(x))
const ll ADD=19980731;//为了方便初始化,边权都加上某个值 
int n,mat[505],pre[505];
ll w[505][505],exg[505],exb[505],lak[505];
bool vb[505];
inline void bfs(int pg){
	int x,y=0,by=0;ll ad;
	mst0(pre);
	memset(lak,0x7f,sizeof(lak));
	mat[y]=pg;
	do{
		x=mat[y],ad=INF,vb[y]=1;
		for(int i=1;i<=n;i++)
			if(!vb[i]){
				ll gap=exg[x]+exb[i]-w[x][i];
				if(lak[i]>gap)lak[i]=gap,pre[i]=y;
				if(lak[i]<ad)ad=lak[i],by=i;
			}
		for(int i=0;i<=n;i++){
			if(vb[i])exg[mat[i]]-=ad,exb[i]+=ad;
			else lak[i]-=ad;
		}
		y=by;
	}while(mat[y]!=0);
	while(y)mat[y]=mat[pre[y]],y=pre[y];
}
inline ll KM(){
	mst0(mat);mst0(exb);mst0(exg);
	for(int i=1;i<=n;i++)mst0(vb),bfs(i);
	ll res=0;
	for(int i=1;i<=n;i++)res+=w[mat[i]][i]-ADD;
	return res;
}

SPFA求费用流模板

重拾SPFA

ll w[MAXM],c[MAXM],f[MAXN],d[MAXN],ansf,ansc;
int pre[MAXN],las[MAXN];
struct edge{
	int v,id;edge(){}
	edge(int V,int I){v=V,id=I;}
};
vector<edge>G[MAXN];
bool vis[MAXN];
queue<int>q;

inline bool SPFA(int S,int T){
	memset(d,0x7f,sizeof(d));
	memset(vis,0,sizeof(vis));
	memset(f,0x7f,sizeof(f));
	q.push(S),d[S]=0,vis[S]=1,pre[T]=-1;
	while(!q.empty()){
		int u=q.front();q.pop(),vis[u]=0;
		for(int i=0;i<G[u].size();i++){
			int v=G[u][i].v,a=G[u][i].id;
			if(w[a]>0&&d[v]>d[u]+c[a]){
				d[v]=d[u]+c[a],f[v]=min(f[u],w[a]);
				pre[v]=u,las[v]=a;
				if(!vis[v])vis[v]=1,q.push(v);
			}
		}
	}
	return pre[T]>=0;
}
inline void ildfs(int S,int T){    //Illusory-DFS,虚假深搜
	ansf+=f[T],ansc+=f[T]*d[T];
	for(int x=T;x!=S;x=pre[x])
		w[las[x]]-=f[T],w[las[x]^1]+=f[T];
}

前向星改进版:

#define ll long long
#define INF 1e17
struct edge{
	int v,to;ll c,f;edge(){}
	edge(int V,ll C,ll F,int T){v=V,c=C,f=F,to=T;}
}e[1000005];
int EN=1,G[MAXN],ps;
inline void addedge(int u,int v,ll c,ll f){
	e[++EN]=edge(v,c,f,G[u]),G[u]=EN;
	e[++EN]=edge(u,-c,0,G[v]),G[v]=EN;
}
ll ds[MAXN],f[MAXN],ansf,ansc;
int pre[MAXN];
bool inq[MAXN];
queue<int>q;
inline bool SPFA(int S,int T){
	for(int i=1;i<=ps;i++)ds[i]=f[i]=INF;
	q.push(S),inq[S]=1,ds[S]=0,pre[S]=0,pre[T]=-1;
	while(!q.empty()){
		int u=q.front();q.pop(),inq[u]=0;
		for(int i=G[u];i;i=e[i].to){
			int v=e[i].v;
			if(e[i].f>0&&ds[v]>ds[u]+e[i].c){
				ds[v]=ds[u]+e[i].c,f[v]=min(f[u],e[i].f);
				pre[v]=i;
				if(!inq[v])inq[v]=1,q.push(v);
			}
		}
	}return pre[T]>=0;
}
inline void ildfs(int S,int T){
	ansf+=f[T],ansc+=f[T]*ds[T];
	for(int x=T;x^S;x=e[pre[x]^1].v)
		e[pre[x]].f-=f[T],e[pre[x]^1].f+=f[T];
}

三种最小生成树算法

算法之前(Kruskal、Boruvka)

#define uns unsigned
int n,fa[MAXN];
inline int findset(int x){  //Kruskal、Boruvka都要用到并查集
	return fa[x]==0?x:(fa[x]=findset(fa[x]));
}
struct edge{
	int v,w;edge(){}
	edge(int V,int W){v=V,w=W;}
};
struct edge_{
	int u,v,w;edge_(){}
	edge_(int U,int V,int W){u=U,v=V,w=W;}
	bool operator<(const edge3&b)const{
		if(w!=b.w)return w<b.w;
		else if(u!=b.u)return u<b.u;
		else return v<b.v;
	}
}e[MAXN];
vector<edge>G[MAXN],T[MAXN];//G为原图,T为生成树
vector<edge_>ad;

Kruskal(首选)

适用于边少(≤500000)点多的情况,复杂度O(m\log m)

inline void Kruskal(){
	ad.clear();
	memset(fa,0,sizeof(fa));
	for(int u=1;u<=n;u++)
		for(uns i=0;i<G[x].size();i++)
			ad.push_back(edge_(u,G[x][i].v,G[x][i].w));
	sort(ad.begin(),ad.end());
	for(uns i=0;i<ad.size();i++){
		int u=ad[i].u,v=ad[i].v;
		if(findset(u)!=findset(v)){
			T[u].push_back(edge(v,ad[i].w));
			T[v].push_back(edge(u,ad[i].w));
			fa[findset(v)]=findset(u);
		}
	}
}

Prim(用的少)

Prim适用于点少(≤5000)的完全图,也就是边数为n^2级别的题,复杂度O(n^2),它会比Kruskal少一个log,所以说是无奈之选

//前面部分的代码准备不一样,请自行脑补

inline int Prim(){ //邻接矩阵
    int an=0; //生成树边的总长
    memset(v,0,sizeof(v)),v[1]=1;
    for(int i=1;i<=n;i++)w[i]=c[1][i]; //连通块连向其他点的边权
    for(int K=1;K<n;K++){
    	int u=1,ad=0x3f3f3f3f;
	    for(int i=1;i<=n;i++)if(!v[i]&&w[i]<ad)ad=w[i],u=i;
    	an+=ad,v[u]=1;
    	for(int i=1;i<=n;i++)w[i]=min(w[i],c[u][i]);
    }
    return an;
}

Boruvka(高级)

每次找每个连通块出发边权最小的边并连接,一次下来,连通块数量减半,最多做\log n次。一般情况,它的复杂度是O(m\log n)

对于点多(≤500000)的完全图,边数为n^2级别,但两点之间的边有特殊规律的题,它可以更快。假设从一个点,找到一条边权最小的连向与自己未连通的点的边,最少需要时间O(C),那么它的复杂度为O(nC\log n)

inline void Boruvka(){
	int num=n;
	memset(fa,0,sizeof(fa));
	while(num>1){
		ad.clear();
		for(int i=1;i<=n;i++)e[i]=edge_(0,0,2e9);
		for(int u=1;u<=n;u++)
		    //下面的找边过程可根据题目的性质优化 
			for(uns i=0;i<G[u].size();i++){
				int v=G[u][i].v,w=G[u][i].w,x=findset(u);
				if(findset(u)!=findset(v))
					e[x]=min(e[x],edge_(u,v,w));
			}
		    //
		for(int i=1;i<=n;i++)if(e[i].u)ad.push_back(e[i]);
		for(uns i=0;i<ad.size();i++){
			int u=findset(ad[i].u),v=findset(ad[i].v);
			if(u!=v){
				T[ad[i].u].push_back(edge(ad[i].v,ad[i].w));
				T[ad[i].v].push_back(edge(ad[i].u,ad[i].w));
				fa[v]=u,num--;
			}
		}
	}
}

浮点数高斯消元

const double MN=1e-13;//判0
double c[MAXN][MAXN],x[MAXN]; //c:增广矩阵,x:变量的解
inline int Gauss(int n,int m,int&tm){//m个变量,n个方程,tm统计行的交换次数(用于计算行列式)
	for(int i=0;i<=m;i++)x[i]=0; //预处理
	int col,row;
	for(row=0,col=0;row<n&&col<m;row++,col++){
		int mxr=row;//找当前列绝对值最大的行
		for(int i=row+1;i<n;i++)
			if(fabs(c[i][col])>fabs(c[mxr][col]))mxr=i;
		if(mxr!=row&&(++tm))
			for(int j=col;j<=m;j++)swap(c[row][j],c[mxr][j]);
		if(fabs(c[row][col])<MN){row--;continue;}//这列已经清零,继续做下一列,但不能放弃这行
		for(int i=row+1;i<n;i++){//消元
			if(fabs(c[i][col])<MN)continue;
			double g=c[i][col]/c[row][col];
			c[i][col]=0;
			for(int j=col+1;j<=m;j++)c[i][j]-=c[row][j]*g;
		}
	}
	for(int i=row;i<n;i++)//无解
		if(fabs(c[i][col])>=MN)return -1;
	if(row<m)return m-row;//无数解、有自由元
	for(int i=n-1;i>=0;i--){//唯一解
		double b=c[i][m];
		for(int j=i+1;j<m;j++)b-=c[i][j]*x[j];
		x[i]=b/c[i][i];
	}
	return 0;
}//无解返回-1,唯一解返回0,否则返回自由元个数

*注:这是一个大常数板子,有小常数板子的,不妨推荐给我吧👀

模线性高斯消元

inline int ksm(int a,int b,int mo){//和浮点数唯一不同是求逆元需要用到快速幂
    int res=1;
	for(;b;b>>=1,a=a*a%mo)if(b&1)res=res*a%mo;
	return res;
}
int c[MAXN][MAXN],x[MAXN];
inline int Gauss(int n,int m,int mo,int&tm){//这里默认模数为质数,否则要求phi
	for(int i=0;i<=m;i++)x[i]=0;
	int col,row;
	for(row=0,col=0;row<n&&col<m;row++,col++){
		int mxr=row;
		for(int i=row+1;i<n;i++)
			if(abs(c[i][col])>abs(c[mxr][col]))mxr=i;
		if(mxr!=row&&(++tm))
			for(int j=col;j<=m;j++)swap(c[row][j],c[mxr][j]);
		if(!c[row][col]){row--;continue;}
		int inv=ksm(c[row][col],mo-2,mo);//预先存下逆元,保证复杂度仍为n^3
		for(int i=row+1;i<n;i++){
			if(!c[i][col])continue;
			int g=c[i][col]*inv;
			c[i][col]=0;
			for(int j=col+1;j<=m;j++)
				c[i][j]=(c[i][j]-c[row][j]*g%mo+mo)%mo;
		}
	}
	for(int i=row;i<n;i++)//无解 
		if(c[i][col]>0)return -1;
	if(row<m)return m-row;//无数解 
	for(int i=n-1;i>=0;i--){//唯一解 
		int b=c[i][m];
		for(int j=i+1;j<m;j++)b=(b-c[i][j]*x[j]%mo+mo)%mo;
		x[i]=b*ksm(c[i][i],mo-2,mo)%mo;
	}
	return 0;
}

普通BSGS(大步小步算法)

保证底数与模数互质

ll B;
map<ll,int>mp;
inline ll BSGS(ll a,ll b,ll c){//a^x=b mod c
	if(a%c==1&&b%c!=1)return -1;
	if(b%c==1)return 0;
	if(a%c==b%c)return 1;
	B=ceil(sqrt(c))+5,a%=c,b%=c;
	ll cg=ksm(a,B,c),g;
	mp.clear(),g=b*a%c;
	for(int i=1;i<=B;i++)mp[g]=i,g=g*a%c;
	g=cg;
	for(int i=1;i<=B;i++){
		if(mp.find(g)!=mp.end())return B*i-mp[g];
		g=g*cg%c;
	}
	return -1;
}

exBSGS(扩展大步小步算法)

不保证底数与模数互质

ll B;
map<ll,int>mp;
inline ll exBSGS(ll a,ll b,ll c){
	if(a%c==1&&b%c!=1)return -1;
	if(b%c==1)return 0;
	if(a%c==b%c)return 1;
	ll v=1,e=0,gc;
	while((gc=gcd(a,gcd(b,c)))>1){
		b/=gc,c/=gc,v=v*(a/gc)%c,e++;
		if(v%c==b%c)return e;
	}
	if(gcd(a,c)>1)return -1;
	B=ceil(sqrt(c))+5,a%=c,b%=c,v%=c;
	ll cg=ksm(a,B,c),g;
	mp.clear(),g=b*a%c;
	for(int i=1;i<=B;i++)mp[g]=i,g=g*a%c;
	g=v*cg%c;
	for(int i=1;i<=B;i++){
		if(mp.find(g)!=mp.end())return B*i-mp[g]+e;
		g=g*cg%c;
	}
	return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值