zr2019暑期高端峰会AB组day1

本文深入探讨了算法竞赛中的策略与技巧,通过分析具体题目,如小K与集合、小K与数据、小K与奇数,展示了如何从问题本质出发,设计高效算法解决方案。文章涵盖了暴力解法、优化策略、数据结构应用及复杂度分析,为参赛者提供了宝贵的实战经验。

zr2019暑期高端峰会AB组day1

A. 小K与集合

这道题我在考场起码思考了两个小时,总觉得能想出什么,但其实就差一步了,我真是又傻逼又菜,连暴力都写T了,期望得分45,实际得分15,挂掉了暴力,判掉了全部元素相同和不同。

心路历程

以下是大概我前一个小时想的内容:

  • 首先题目说什么什么有概率,又问必定成功的方案,其实就是要我们每一步都考虑最坏情况,我们想象对面有个人每次尽可能的阻止我达成目标,留下最废的一堆给我。
  • 由于每次都最坏,所以分组不能太集中,要尽量平均,最小化损失,否则如果一堆数放一组直接被对方删掉就GG了
  • 某个时刻当1的个数 ≥ k \geq k k时,我就赢了,我在1放在每一组里都有就行。这个情况可以稍微推广到,比如有至少k个1必胜,由于k个2在一轮之后我只能保证一个1存活下来,所以至少有 k 2 k^2 k2个2必胜,推广到至少有 k i k^i ki个i必胜,于是我们就判掉了所有元素相同和不同(不同无解)
  • (下面就想偏了)当1的个数小于k时虽然不能必胜,但是我可以前面的几组只单放一个1,然后剩下很多再在后面几组平均发放,于是就有点想直接模拟这个过程,但是万一不能平均,有余数怎么办,于是就疯狂想这个,然后我人就没了

正解

其实第三点中的本质就是k个i可以换一个i-1,于是这就像往前进位,看看能不能换来一个0,就是0位上有没有数,然后这题就没了。
然后我才突然发现我判断全部元素相同的过程(118-123行)其实就是在进位啊!!我竟然这么傻逼

考场的又臭又长菜鸡代码
#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b)i;--)
#define mem(i,j) memset(i,j,sizeof(i))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1e5+5;
int t,n,k,a[N],f[N],pos1[N],pos2[N],vis[N],nxt[N],last[N],g[N];
vector <int> T[N];
int task1,task2,task3;
//Task1
int s[1<<11],ans1[11],ans2[11];
vector <int> G[11];
//
//Task3
map<int,int> mp;
//
int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
void Judge()
{
	task1=0;
	if (n<=10&&k==2) task1=1;
	task2=1;
	FOR(i,1,n) if (a[i]!=a[1]) task2=0;
	task3=1;
	FOR(i,1,n)
	{
		if (mp[a[i]]) task3=0;
		mp[a[i]]++;
	}
	FOR(i,1,n) mp[a[i]]=0;
	return;
}
int DFS(int siz,int *A)
{
	FOR(i,1,siz) if (A[i]==0) return 1;
	if (siz<k) return 0;
	int cnt=0;
	FOR(i,1,siz) if (A[i]==1) cnt++;
	if (cnt>=2) 
	{
		if (siz==n)
		{
			int pos=0;
			FOR(i,1,siz) if (A[i]==1) pos=i;
			FOR(i,1,siz)
			{
				if (i!=pos) ans1[++ans1[0]]=i;
				else ans2[++ans2[0]]=i;
			}
		}
		return 1;
	}
	int b[2][11],tag[2];
	int len=G[siz/2].size();
	FOR(i,0,len-1)
	{
		int msk=G[siz/2][i];
		int p1=0,p2=0;
		tag[0]=tag[1]=0;
		FOR(j,0,siz-1)
		{
			if ((msk>>j)&1) b[0][++p1]=A[j+1]-1;
			else b[1][++p2]=A[j+1]-1;
		}
		tag[0]=DFS(siz/2,b[0]);
		tag[1]=DFS((siz+1)/2,b[1]);
		if (tag[0]&&tag[1])
		{
			if (siz==n) 
			{
				FOR(j,0,siz-1)
				{
					if ((msk>>j)&1) ans1[++ans1[0]]=j+1;
					else ans2[++ans2[0]]=j+1;
				}
			}
			return 1;
		}
	}
	return 0;
}
void Init()
{
	FOR(i,0,(1<<10)-1)
		FOR(j,0,10-1)
			if ((i>>j)&1) s[i]++;
	return;
}
void Task1()
{
	ans1[0]=ans2[0]=0;
	FOR(i,0,(1<<n)-1) G[s[i]].pb(i);
	if (DFS(n,a))
	{
		printf("1\n");
		printf("%d ",ans1[0]);
		FOR(i,1,ans1[0]) printf("%d ",ans1[i]);
		printf("\n");
		printf("%d ",ans2[0]);
		FOR(i,1,ans2[0]) printf("%d ",ans2[i]);
		printf("\n");
	}
	else printf("0\n");
	return;
}
void Task2()
{
	int cnt=n,now=a[1],ok=0;
	while (cnt)
	{
		cnt/=k;
		now--;
		if (now==1&&cnt>=k) ok=1;
	}
	if (ok)
	{
		int cnt1=n%k,cnt2=0;
		printf("1\n");
		if (cnt1) FOR(i,1,cnt1)
		{
			printf("%d ",n/k+1);
			FOR(j,1,n/k+1) printf("%d ",++cnt2);
			printf("\n");
		}
		FOR(i,1,k-cnt1)
		{
			printf("%d ",n/k);
			FOR(j,1,n/k) printf("%d ",++cnt2);
			printf("\n");
		}
	}
	else printf("0\n");
	return;
}
void Task3()
{
	printf("0\n");
	return;
}
void Solve()
{
	int ok=0,tag=0,mx=0;
	FOR(i,1,n) f[a[i]]++;
	FOR(i,1,n) if (f[i]>=k) tag=1,mx=max(mx,i);
	if (!tag)
	{
		printf("0\n");
		return;
	}
	tag=0;
	FOR(i,1,n) g[i]=f[i];
	FOR(i,1,n/k)
	{
		int tmpk;
		if (g[1+tag]>=k) 
		{
			ok=1;
			break;
		}
		else tmpk=k-g[1+tag];
		FOR(j,1,mx-tag) 
			g[j+tag]/=tmpk;
		tag++;
	}
	if (ok)
	{
		printf("1\n");
		if (f[1]>=k)
		{
			int now1=0;
			FOR(i,1,n) vis[i]=0;
			FOR(i,1,n) if (a[i]==1&&now1<k-1)
			{
				now1++;
				vis[i]=1;
				printf("1 %d\n",i);
			}
			printf("%d ",n-k+1);
			FOR(i,1,n) if (!vis[i]) printf("%d ",i);
			printf("\n");
		}
		else 
		{
			FOR(i,1,n) vis[i]=0;
			FOR(i,1,n) if (a[i]==1) printf("1 %d\n",i),vis[i]=1;
			int tmpk=k-f[1];
			FOR(i,2,tmpk) nxt[i]=i-1;
			nxt[1]=tmpk;
			FOR(i,1,n) last[i]=1;
			FOR(i,1,tmpk) T[i].clear();
			FOR(i,1,n) if (!vis[i]) T[nxt[last[a[i]]]].pb(i),last[a[i]]=nxt[last[a[i]]];
			FOR(i,1,tmpk)
			{
				int len=T[i].size();
				printf("%d ",len);
				FOR(j,0,len-1) printf("%d ",T[i][j]);
				printf("\n");
			}
		}
	}
	else printf("0\n");
	return;
}
int main()
{
//	freopen("data1.in","r",stdin);
	Init();
	t=read();
	while (t--)
	{
		n=read(),k=read();
		FOR(i,1,n) a[i]=read();
		Judge();
		if (task1) Task1();
		else if (task2) Task2();
		else if (task3) Task3();
		else Solve();
	//	printf("//////////////////////////////////\n");
	}
	return 0;
}
赛后的代码
#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1e5+5;
int t,n,k,a[N],f[N],g[N];
vector <int> G[N],T[N];
int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
int main()
{
//	freopen("data1.in","r",stdin);
	t=read();
	while (t--)
	{
		n=read(),k=read();
		FOR(i,0,n) G[i].clear(),f[i]=g[i]=0;
		FOR(i,1,k) T[i].clear();
		FOR(i,1,n) a[i]=read(),G[a[i]].pb(i);
		FOR(i,1,n) f[a[i]]++;
		For(i,n,0) g[i]=f[i]+g[i+1]/k;
		if (g[0]>=1)
		{
			int now=1,nowneed=1,need=1;
			FOR(i,1,n)
			{
				int len=G[i].size();
				FOR(j,0,len-1)
				{
					int pos=G[i][j];
					T[now].pb(pos);
					need--;
					if ((!need)&&now<k) now++,need=nowneed;
				}
				nowneed*=k,need*=k;
			}
			printf("1\n");
			FOR(i,1,k)
			{
				int len=T[i].size();
				printf("%d ",len);
				FOR(j,0,len-1) printf("%d ",T[i][j]);
				printf("\n");
			}
		}
		else printf("0\n");
	}
	return 0;
}

B. 小K与数据

原来并查集可以42分啊,我是傻逼吧我为什么不写并查集,又好写又有分
我写了一个 O ( n q ) O(nq) O(nq)的BFS期望得分22,但是我为什么这垃圾啊写了一个vis数组没有用上,我真是傻逼

正解

  • 小性质:对于一对区间,如果它们的重叠长度大于自身的一半,那么这两段区间的并集就是一段周期串,周期为 l 2 − l 1 l_2-l_1 l2l1
  • 我们对于每一对区间右区间的点向左边连边
  • 有了右区间不重叠的性质,那么每一个点只能出现在一个右区间中,那么每个点都这样向左连边形成的就是一个树结构,因为我们随机生成树的数据的时候就是这样做的
  • 那么我们每次插入或者查询一个位置的字符时候,就一直往左边跳,每次跳的时候在经过的区间上标记,最终把信息留在在某棵树的树根,然后每个区间的标记怎么打呢,我们利用第一个小性质,直接记录在模周期余几时可以取到该字符
  • 所以每次我们跳一次就必定跳出一个区间,区间最多n个,这样复杂度就对了, O ( n 2 ) O(n^2) O(n2)
考场代码

考场上没有写

if (!vis[...])

并查集是来赛后试了一发

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b)i;--)
#define mem(i,j) memset(i,j,sizeof(i))
using namespace std;
typedef long long ll;
const int N=1e6+5;
int n,m1,m2,q,p[N],opt[N],a,b,c,d;
int fa[N];
int task1,task2;
char ch[N][2],s[N],ans[N];
//task2
int vis[N],l,r,line[N];
//
struct seg
{
	int l1,r1,l2,r2;
}f[N];
int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
void Judge()
{
	task1=task2=0;
	if (n==m1) task1=1;
	if (n<=1000) task2=1;
	return;
}
void Task1()
{
	FOR(i,1,m1) s[p[i]]=ch[i][1];
	FOR(i,1,q) ans[i]=s[opt[i]];
	FOR(i,1,q) printf("%c\n",ans[i]);
	return;
}
void Task2()
{
	FOR(i,1,m1) s[p[i]]=ch[i][1];
	FOR(i,1,q)
	{
		FOR(j,1,n) vis[j]=0;
		r=0,l=1;
		line[++r]=opt[i];
		while (l<=r)
		{
			int tmp=line[l++];
			vis[tmp]++;
			if (s[tmp]!='?')
			{
				ans[i]=s[tmp];
				break;
			}
			FOR(j,1,m2)
			{
				if (f[j].l1<=tmp&&tmp<=f[j].r1) if (!vis[tmp-f[j].l1+f[j].l2]) line[++r]=tmp-f[j].l1+f[j].l2;
				if (f[j].l2<=tmp&&tmp<=f[j].r2) if (!vis[tmp-f[j].l2+f[j].l1]) line[++r]=tmp-f[j].l2+f[j].l1;
			}
		}
	}
	FOR(i,1,q) printf("%c\n",ans[i]);
	return;
}
int Getfa(int x)
{
	return (x==fa[x])?x:fa[x]=Getfa(fa[x]);
}
void Join(int x,int y)
{
	int fx=Getfa(x),fy=Getfa(y);
	if (fx!=fy) fa[fx]=fy;
	return;
}
int main()
{
//	freopen("data2.in","r",stdin);
	n=read(),m1=read(),m2=read(),q=read();
	FOR(i,1,n) fa[i]=i;
	FOR(i,1,m1) p[i]=read(),scanf("%s",ch[i]+1);
	FOR(i,1,m2) a=read(),b=read(),c=read(),d=read(),f[i]=(seg){a,b,c,d};
	FOR(i,1,q) opt[i]=read();
	FOR(i,1,m2) 
		FOR(j,1,f[i].r1-f[i].l1+1)
			Join(f[i].l1+j-1,f[i].l2+j-1);
	FOR(i,1,n) s[i]='?';
	FOR(i,1,m1) s[Getfa(p[i])]=ch[i][1];
	FOR(i,1,q) ans[i]=s[Getfa(opt[i])];
	FOR(i,1,q) printf("%c\n",ans[i]);
	return 0;
} 
赛后的代码
#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1005;
int n,m1,m2,q,a,b,c,d,pos[N],p[N],opt[N];
char ch[N][2],ans[N];
map <int,char> mp;
struct seg
{
	int l1,r1,l2,r2,T;
	map <int,char> mp;
}f[N];
bool cmpr2(const seg s1,const seg s2)
{
	return s1.r2<s2.r2;
}
int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
int Which_s2(int x)
{
	int s2=lower_bound(pos+1,pos+m2+1,x)-pos;
	if (s2<1||s2>m2||f[s2].l2>x) return -1;
	else return s2;
}
void Insert(int x,int cha)
{
	int s2=Which_s2(x);
	if (s2==-1)
	{
		mp[x]=cha;
		return;
	}
	f[s2].mp[x%f[s2].T]=cha;
	x=x-((x-f[s2].l1)/f[s2].T)*f[s2].T;
	Insert(x,cha);
	return;
}
char Query(int x)
{
	if (mp.count(x)) return mp[x];
	int s2=Which_s2(x);
	if (s2==-1)
	{
		if (mp.count(x)) return mp[x];
		else return '?';
	}
	if (f[s2].mp.count(x%f[s2].T)) return f[s2].mp[x%f[s2].T];
	x=x-((x-f[s2].l1)/f[s2].T)*f[s2].T;
	return Query(x);
}
int main()
{
//	freopen("data2.in","r",stdin);
	n=read(),m1=read(),m2=read(),q=read();
	FOR(i,1,m1) p[i]=read(),scanf("%s",ch[i]+1);
	FOR(i,1,m2) f[i].l1=read(),f[i].r1=read(),f[i].l2=read(),f[i].r2=read();
	FOR(i,1,q) opt[i]=read();
	sort(f+1,f+m2+1,cmpr2);
	FOR(i,1,m2)
	{
		pos[i]=f[i].r2;
		f[i].T=f[i].l2-f[i].l1;
	}
//	FOR(i,1,m2) printf("%d %d %d %d %d\n",f[i].l1,f[i].r1,f[i].l2,f[i].r2,f[i].T);
	FOR(i,1,m1) Insert(p[i],ch[i][1]);
	FOR(i,1,q) ans[i]=Query(opt[i]);
	FOR(i,1,q) printf("%c\n",ans[i]);
	return 0;
}

C. 小K与奇数

这题感觉暴力都不是很好写,十分的完全图就是每次每次四个四个地加点,新的四个点和原来的点构成二分图,它们之间把边跳完跳出一条路径,然后这新的四个点再按样例的方式连边

正解

  • 每一个点是且仅是一条路径的端点,所以每个点的度数必定是奇数,由于所有的路径长度都是偶数,所以边数必定是偶数,这样就判掉了无解的情况
  • 假设先忽略路径长度为偶数的限制,那么随机匹配 n 2 \frac{n}{2} 2n对点,连上虚边使它们的度数变成偶数,跑一个欧拉回路,虚边有 n 2 \frac{n}{2} 2n条于是刚好把这条欧拉回路断成了 n 2 \frac{n}{2} 2n符合题意条路径
  • 于是现在我们考虑用长度为2的边对原图做一个覆盖,使得每一条边被覆盖且仅被覆盖一次,这样我们得到了一个新图,旧边不看(两条旧边的编号贴在新边上),在新图上跑欧拉回路就把问题变成了上面那个
  • 我们仔细观察发现做完覆盖后每个点的度数奇偶性不会变,于是就过掉了
  • 还有就是怎么求这个覆盖,也就是怎么建出新图。DFS,对于每条不在DFS树上的非树边(它们必定全是返祖边,因为DFS),我们在它的上端点安排它的匹配,对于每一个点,将通向儿子的边尽可能互相匹配,这个DFS有个返回值,就是该点的父亲边有没有被匹配,这个东西在它的父节统计时有用,于是就过掉了
赛后代码
#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define pb push_back
#define mem(i,j) memset(i,j,sizeof(i))
using namespace std;
const int N=4e5+5;
int n,m,x,y,lim,du[N],not_good=0;
int vis[N],inq[N],used[N];
int first[N],nxxt[N<<1],tote=1;
int f[N],nxt[N<<1],tot=1;
vector <vector<int> > ans;
struct E
{
	int u,v,id1,id2;
}edge[N<<1],e[N<<1];
int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
void Addedge(int u,int v)
{
	tote++;
	nxxt[tote]=first[u];
	first[u]=tote;
	edge[tote]=(E){u,v,0,0};
	return;
}
void Make_edge(int u,int v,int id1,int id2)
{
	tot++;
	nxt[tot]=f[u];
	f[u]=tot;
	e[tot]=(E){u,v,id1,id2};
	return;
}
void Pair_edge(int &cur,int j,int u)
{
	if (!cur)
	{
		cur=j;
		return;
	}
	int uu,vv;
	if (u==edge[cur].v) uu=edge[cur].u;
	else uu=edge[cur].v;
	if (u==edge[j].v) vv=edge[j].u;
	else vv=edge[j].v;
	Make_edge(uu,vv,cur>>1,j>>1);
	Make_edge(vv,uu,j>>1,cur>>1);
//	printf("%d %d %d %d %d %d\n",uu,vv,edge[cur].u,edge[cur].v,edge[j].u,edge[j].v);
	cur=0;
	return;
}
int DFS(int u,int pre_e)//父边匹配返回1 
{
	int cur=0;
	vis[u]=inq[u]=1;
	for (register int j=first[u];j!=-1;j=nxxt[j])
	{
		int v=edge[j].v;
		if (!vis[v])
		{
			if (!DFS(v,j)) Pair_edge(cur,j,u);
		}
		else if (!inq[v]) Pair_edge(cur,j,u);
	}
	inq[u]=0;
	if (!cur) return 0;//目前已经刚好匹配,父边未匹配 
	if (pre_e) Pair_edge(cur,pre_e,u);
	return 1;
}
void Euler(int u)
{
	for (register int j=f[u];j!=-1;j=nxt[j]) if (!used[j>>1])
	{
		used[j>>1]=1;
		int v=e[j].v;
		Euler(v);
		if (j>lim)
		{
			if (ans.empty()||(!ans.back().empty())) ans.pb(vector<int>());
		}
		else
		{
			ans.back().pb(e[j].id2);
			ans.back().pb(e[j].id1);
		}
	}
	return;
}
int main()
{
	mem(f,-1);
	mem(first,-1);
	n=read(),m=read();
	FOR(i,1,m) x=read(),y=read(),Addedge(x,y),Addedge(y,x),du[x]++,du[y]++;
	FOR(i,1,n) if (du[i]%2==0) not_good=1;
	if ((not_good)||(m%2==1)) {printf("0\n");exit(0);}
	FOR(i,1,n)
		if (!vis[i]) DFS(i,0);
	lim=tot;
	for (int i=1;i<n;i+=2) Make_edge(i,i+1,-1,-1),Make_edge(i+1,i,-1,-1);
	ans.pb(vector<int>());
	FOR(i,1,n) Euler(i);
	while (ans.back().empty()) ans.pop_back();
	printf("1\n");
	int len1=ans.size();
	FOR(i,0,len1-1)
	{
		int len2=ans[i].size();
		printf("%d ",len2);
		FOR(j,0,len2-1) printf("%d ",ans[i][j]);
		printf("\n");
	}
	return 0;
}
代码下载地址: https://pan.quark.cn/s/35e46f7e83fb 关于 Build Status Lines of code 这是一个参考 PotPlayer 的界面使用 Java 以及图形界面框架 JavaFX 使用 MCV 图形界面与业务逻辑分离的开发模式, 所开发的个人视频播放器项目, 开发这个项目旨在于学习图形界面框架 JavaFX 实现了具有和 PotPlayer相同 的简洁界面和流畅的操作逻辑。 Note: PotPlayer 是 KMPlayer 的原制作者姜龙喜先生(韩国)进入 Daum 公司后的 新一代网络播放器, PotPlayer的优势在于强大的内置解码器以及支持各类的 视频格式, 而且是免费下载提供使用的。 目前版本: 2020/10/28 v1.0.0 [x] 支持打开文件自动播放 [x] 支持查看播放记录 [x] 支持屏幕边沿窗口自动吸附 [x] 支持双击视频来播放和暂停 [x] 支持左键点击窗口任意位置来拖到窗口 [x] 支持左键双击播放窗口打开文件 [x] 支持根据视频尺寸自动调整窗口大小 [x] 支持根据播放文件类型调整窗口模式 [x] 支持根据视频尺寸自动调整窗口显示位置防止超出屏幕 [x] 支持记录上一次访问的文件路径 [x] 支持播放记录文件读写 已实现样式 未播放效果: 播放效果: 运行环境 本项目使用 NetBeans 配合 JDK 开发, NetBeans8.0 以及 JDK8.0 以上版本的均可以运行。 亦可使用其他集成开发环境, 例如 Eclipse, IntelliJ IDEA 配合使用 JDK8.0 以上版本均可构建此项目。 NetBeans download Eclipse downlo...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值