省选模拟 19/10/11 (LibreOJ NOI Round #2)

「LibreOJ NOI Round #2」单枪匹马
比较容易想到分子分母分开维护
x i y i = a i + y i + 1 x i + 1 = a i ∗ x i + 1 + y i + 1 x i + 1 \frac{x_i}{y_i}=a_i+\frac{y_{i+1}}{x_{i+1}}=\frac{a_i*x_{i+1}+y_{i+1}}{x_{i+1}} yixi=ai+xi+1yi+1=xi+1aixi+1+yi+1
好像可以矩阵乘
( x i , y i ) = ( x i + 1 , y i + 1 ) ( a i , 1 1 , 0 ) (x_i,y_i)=(x_{i+1},y_{i+1})\binom{a_i,1}{1,0} (xi,yi)=(xi+1,yi+1)(1,0ai,1)
然后就可以线段树维护了, l o j loj loj 可过,但被学校的老爷机卡飞
考虑到只会从后面插点,是不是可以前缀和呢,常识构造一个逆矩阵
( a i , 1 1 , 0 ) ∗ ? = ( 1 , 0 0 , 1 ) \binom{a_i,1}{1,0}*?=\binom{1,0}{0,1} (1,0ai,1)?=(0,11,0) ( a i , 1 1 , 0 ) ∗ ( 0 , 1 1 , − a i ) = ( 1 , 0 0 , 1 ) \binom{a_i,1}{1,0}*\binom{0,1}{1,-a_i}=\binom{1,0}{0,1} (1,0ai,1)(1,ai0,1)=(0,11,0)
然后就可以 O ( n + m ) O(n+m) O(n+m) 做了
学到了矩阵也可以构造逆元…

#include<bits/stdc++.h>
#define N 1000050
using namespace std;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
	while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
	return cnt * f;
}
const int Mod = 998244353;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b;}
int mul(int a, int b){ return 1ll * a * b % Mod;}
void Add(int &a, int b){ a = add(a, b);}
int n, m, typ, a[N], ret;
int ansx, ansy;
struct matrix{
	int a[2][2];
	matrix(){ memset(a, 0, sizeof(a)); }
	matrix operator * (const matrix &A){
		matrix B; for(int i = 0; i < 2; i++)
			for(int j = 0; j < 2; j++) for(int k = 0; k < 2; k++)
		 		Add(B.a[i][j], mul(a[i][k], A.a[k][j]));
		return B;
	}
} sum[N], inv[N];
int main(){
	n = ret = read(), m = read(), typ = read();
	sum[0].a[0][0] = sum[0].a[1][1] = inv[0].a[0][0] = inv[0].a[1][1] = 1;
	for(int i = 1; i <= n; i++){
		a[i] = read();
		matrix A; A.a[0][0] = a[i]; A.a[0][1] = A.a[1][0] = 1;
		matrix B; B.a[0][1] = B.a[1][0] = 1; B.a[1][1] = Mod - a[i];
		sum[i] = sum[i-1] * A;
		inv[i] = B * inv[i-1];
	}
	matrix res; res.a[0][0] = 1;
	for(int i = 1; i <= m; i++){
		int op = read();
		if(op == 1){
			int x = read(); 
			if(typ == 1) x ^= (ansx ^ ansy);
			a[++ret] = x;
			matrix A; A.a[0][0] = x; A.a[0][1] = A.a[1][0] = 1;
			matrix B; B.a[0][1] = B.a[1][0] = 1; B.a[1][1] = Mod - x;
			sum[ret] = sum[ret-1] * A;
			inv[ret] = B * inv[ret-1];
		} 
		if(op == 2){
			int l = read(), r = read();
			if(typ == 1) l ^= (ansx ^ ansy), r ^= (ansx ^ ansy);
			matrix now = inv[l-1] * sum[r] * res;
			ansx = now.a[0][0], ansy = now.a[1][0];
			cout << ansx << " " << ansy << '\n';
		}
	} return 0;
}

「LibreOJ NOI Round #2」黄金矿工
首先费用流的暴力可以拿 8 p t s 8pts 8pts,如果你足够优秀学过消环之类的玄学东西的话好像可以拿不错的分数
先简化一下询问, ( P x + Q y + d i s y − d i s x ) (P_x+Q_y+dis_y-dis_x) (Px+Qy+disydisx),把 P x P_x Px 改成 P x − d i s x P_x-dis_x Pxdisx, P y P_y Py 改成 P y + d i s y P_y+dis_y Py+disy 即可
我们需要给一个点反悔的机会
考虑到如果一个矿工匹配了一个已经匹配过的金矿,这个矿工与另一个矿工也联通了
记原来的矿工为 v 1 v_1 v1,当前为 v 2 v_2 v2,贡献 Δ = v 2 − v 1 \varDelta=v_2-v_1 Δ=v2v1
再转念一想,相当于 v 2 v_2 v2 与一块在当前点权值为 − v 1 -v_1 v1 的金子匹配
然后这边匹配的金子也应该有反悔空间,如果有一个金子强了它的矿工,那么相当与那块金子权值为 − v -v v 的矿工匹配,于是我们每次找到最大的金子/矿工匹配之后,在金子的位置放一个 − v -v v 的矿工,在矿工的位置放一个 − v -v v 的金子
然后从上往下走看做把边的流量加1,如果这条边有流量,就可以向上走表示退流
然后可以每个点开一个堆表示这个点的矿工或者金子
其实主要的思想是:不真正去退流,而是转换条件在不退流的情况下实现退流的意义
暴力的复杂度 O ( n m + m l o g ( m ) ) O(nm+mlog(m)) O(nm+mlog(m))

// 60 pts
#include<bits/stdc++.h>
#define N 100050
using namespace std;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
	while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
	return cnt * f;
}
typedef long long ll; 
int n, m;
vector<int> v[N];
ll dis[N], ans; int dep[N], fa[N], cnt[N];
int home, Max;
void dfs(int u){
	for(int i = 0; i < v[u].size(); i++){
		int t = v[u][i]; 
		dis[t] += dis[u]; fa[t] = u; dep[t] = dep[u] + 1; dfs(t);
	}
}
priority_queue <int> mine[N], gold[N];
void findgold(int u, int las, int inc){
	if(!gold[u].empty() && gold[u].top() + inc > Max){
		Max = gold[u].top() + inc;
		home = u;
	}
	if(fa[u] != las && cnt[u]) findgold(fa[u], u, inc);
	for(int i = 0; i < v[u].size(); i++){
		int t = v[u][i]; if(t != las) findgold(t, u, inc);
	}
}
void findmine(int u, int las, int inc){
	if(!mine[u].empty() && mine[u].top() + inc > Max){
		Max = mine[u].top() + inc;
		home = u;
	}
	if(fa[u] != las) findmine(fa[u], u, inc);
	for(int i = 0; i < v[u].size(); i++){
		int t = v[u][i]; if(t != las && cnt[t]) findmine(t, u, inc);
	}
}
void move(int x, int y){
	while(x^y){ 
		if(dep[y] > dep[x]) ++cnt[y], y = fa[y];
		else --cnt[x], x = fa[x]; 
	}
}
void Mine(int u, int v){ 
	home = Max = 0;
	int val = v - dis[u];
	findgold(u, 0, val);
	if(home){
		move(u, home);
		ans += (ll)Max;
		gold[home].pop();
		gold[u].push(-val);
		mine[home].push(- (Max - val));
	}
	else mine[u].push(val);
}
void Gold(int u, int v){ 
	home = Max = 0;
	int val = v + dis[u];
	findmine(u, 0, val);
	if(home){
		move(home, u);
		ans += (ll)Max;
		mine[home].pop();
		mine[u].push(-val);
		gold[home].push(- (Max - val));
	}
	else gold[u].push(val);
}
int main(){
	n = read(), m = read();
	for(int i = 1; i < n; i++){
		int x = read(), y = read(), z = read();
		v[x].push_back(y); dis[y] = z;
	} dep[1] = 1; dfs(1);
	for(int i = 1; i <= m; i++){
		int op = read(), u = read(), v = read();
		if(op == 1) Mine(u, v);
		if(op == 2) Gold(u, v);
		cout << ans << '\n';
	} return 0;
}

考虑用数据结构模拟这个过程
首先要用一棵线段树维护流量,支持链加,查询最后一个流量 < 0 <0 <0 即不能流的位置
可以维护区间最小然后在线段树上二分
然后加矿工的时候需要退流到最上面的点,最上面的点的子树都可以走到,于是对金矿维护子树最大值及位置,加金矿的时候,对它有贡献的矿工存在的地方是它到根的一条链加上这个这条链上所有点能往下退流到的所有点,发现这个并不好直接维护,我们考虑把矿工的贡献在修改矿工的时候加到金矿里
对于每个金矿,维护一个 s e t set set之类的东西,当插入矿工时,将矿工能退流到的所有金矿的 s e t set set 插入这个矿工,显然暴力插要凉,考虑链分治,一个点维护它的轻儿子的矿工的最大值,跳链的时候改一下即可
整理一下繁琐的细节:
1.我们需要三棵线段树
一棵维护流量,支持区间加区间最小区间二分第一个小于等于0的位置
一棵维护子树黄金的最大值,线段树中还需对每一开一个 s e t set set,支持区间查询
一棵维护每个点轻儿子的最大值,同时支持区间查询
2.每次加减流量或加减矿工只后,要重新把矿工跳一遍,更新矿工对金矿的贡献
然后模拟即可…,代码抄的 zxyoi

#include<bits/stdc++.h>
#define N 100050
using namespace std;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
	while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
	return cnt * f;
}
#define pi pair<int,int>
#define cs const
#define mp make_pair
#define fi first
#define se second
const int INF = 0x7f7f7f7f;
cs pi unit = mp(-INF, 0);
typedef long long ll; 
int n, m; ll ans;
vector<int> v[N];
ll dis[N]; 
int dep[N], fa[N], siz[N], son[N], in[N], out[N], nd[N], bot[N], top[N], sign;
pi las[N];
void dfs(int u){
	siz[u] = 1;
	for(int i = 0; i < v[u].size(); i++){
		int t = v[u][i]; fa[t] = u; dis[t] += dis[u];
		dep[t] = dep[u] + 1; dfs(t); siz[u] += siz[t];
		if(siz[t] > siz[son[u]]) son[u] = t;
	}
}
void dfs2(int u, int Top){
	top[u] = Top; in[u] = ++sign; nd[sign] = u;
	if(son[u]) dfs2(son[u], Top), bot[u] = bot[son[u]];
	else{ bot[u] = u; las[Top] = unit; }
	for(int i = 0; i < v[u].size(); i++) if(v[u][i]^son[u]) dfs2(v[u][i], v[u][i]);
	out[u] = sign;
}
struct SGT{ 
	int mn[N << 2], tg[N << 2];
	void pushup(int x){ mn[x] = min(mn[x<<1], mn[x<<1|1]);}
	void pushtg(int x, int v){ tg[x] += v; mn[x] += v;}
	void pushdown(int x){ if(tg[x]) pushtg(x<<1, tg[x]), pushtg(x<<1|1, tg[x]), tg[x] = 0;}
	void add(int x, int l, int r, int L, int R, int v){
		if(L<=l && r<=R){ pushtg(x, v); return; } 
		pushdown(x); int mid = (l+r) >> 1; 
		if(L<=mid) add(x<<1, l, mid, L, R, v);
		if(R>mid) add(x<<1|1, mid+1, r, L, R, v);
		pushup(x);
	}
	int queryl(int x, int l, int r, int L, int R){
		if(L>R || mn[x] > 0) return -1;
		int mid = (l+r) >> 1; 
		if(L<=l && r<=R){
			if(l == r) return l; pushdown(x);
			int res = queryl(x<<1, l, mid, L, R);
			if(res == -1) res = queryl(x<<1|1, mid+1, r, L, R);
			return res;
		} pushdown(x);
		int res = -1; 
		if(L<=mid) res = queryl(x<<1, l, mid, L, R);
		if(R>mid && res == -1) res = queryl(x<<1|1, mid+1, r, L, R);
		return res;
	} 
	int queryr(int x, int l, int r, int L, int R){
		if(L>R || mn[x] > 0) return -1;
		int mid = (l+r) >> 1;
		if(L<=l && r<=R){ 
			if(l == r) return l;
			pushdown(x); int res = queryr(x<<1|1, mid+1, r, L, R);
			if(res == -1) res = queryr(x<<1, l, mid, L, R);
			return res;
		} pushdown(x); int res = -1;
		if(R>mid) res = queryr(x<<1|1, mid+1, r, L, R);
		if(L<=mid && res == -1) res = queryr(x<<1, l, mid, L, R);
		return res;
	} 
	void update(int L, int R, int v){ add(1, 1, n, L, R, v);}
	int Ql(int L, int R){ return queryl(1, 1, n, L, R);}
	int Qr(int L, int R){ return queryr(1, 1, n, L, R);}
} t1;
struct Segmentree{
	pi mx[N << 2]; set<pi > st[N << 2];
	void pushup(int x){ mx[x] = max(mx[x<<1], mx[x<<1|1]);} 
	void build(int x, int l, int r){
		if(l == r){ mx[x] = unit; return;}
		int mid = (l+r) >> 1; build(x<<1, l, mid); build(x<<1|1, mid+1, r);
		pushup(x);
	}
	void modify(int x, int l, int r, int p, pi pre, pi now){
		if(l == r){
			if(pre.fi != INF) st[x].erase(pre);
			if(now.fi != INF) st[x].insert(now);
			if(st[x].empty()) mx[x] = mp(-INF, nd[l]);
			else mx[x] = *st[x].rbegin();
			return;
		} int mid = (l+r) >> 1;
		if(p <= mid) modify(x<<1, l, mid, p, pre, now);
		else modify(x<<1|1, mid+1, r, p, pre, now);
		pushup(x);
	}
	pi ask(int x, int l, int r, int L, int R){
		if(L<=l && r<=R) return mx[x];
		int mid = (l+r) >> 1;
		if(R<=mid) return ask(x<<1, l, mid, L, R);
		else if(L>mid) return ask(x<<1|1, mid+1, r, L, R);
		else return max(ask(x<<1, l, mid, L, R), ask(x<<1|1, mid+1, r, L, R)); 
	}
	void update(int x, pi pre, pi now){ modify(1, 1, n, x, pre, now); }
	pi query(int l, int r){ return ask(1, 1, n, l, r); }
}t2, t3;
void add(int u, int d){
	while(top[u] != 1){
		t1.update(in[top[u]], in[u], d);
		u = fa[top[u]];
	} if(u != 1) t1.update(2, in[u], d);
}
void modify(int u){
	while(fa[top[u]]){
		int t = t1.Ql(in[top[u]]+1, in[bot[u]]);
		int v = t == -1 ? bot[u] : nd[t-1]; pi tp;
		if(t1.Ql(in[top[u]], in[top[u]]) != -1) tp = unit;
		else tp = t3.query(in[top[u]], in[v]);
		t3.update(in[fa[top[u]]], las[top[u]], tp);
		las[top[u]] = tp;
		u = fa[top[u]];
	}
}
void Mine(int u, int val){
	int v = u;
	for(int t = u, tp; t; t = fa[top[t]]){
		tp = t1.Qr(in[top[t]], in[t]);
		if(tp != -1){ v = nd[tp]; break;}
	} 
	pi t = t2.query(in[v], out[v]);
	if(t.fi + val < 0){
		t3.update(in[u], unit, mp(val, u));
		modify(u);
	}
	else{
		ans += t.fi + val;
		t2.update(in[t.se], t, unit); // del
		t2.update(in[u], unit, mp(-val, u)); // add gold 
		t3.update(in[t.se], unit, mp(-t.fi, t.se)); // add mine
		add(u, -1); add(t.se, 1); modify(u), modify(t.se);
	}
}
void Gold(int u, int val){
	pi p = unit;
	for(int t = u, v, tp; t; t = fa[top[t]]){
		tp = t1.Ql(in[t] + 1, in[bot[t]]);
		v = tp == -1 ? bot[t] : nd[tp - 1];
		p = max(p, t3.query(in[top[t]], in[v]));
	}
	if(p.fi + val < 0){
		t2.update(in[u], unit, mp(val, u));
	}
	else{
		ans += p.fi + val;
		t3.update(in[u], unit, mp(-val, u));
		t3.update(in[p.se], p, unit);
		t2.update(in[p.se], unit, mp(-p.fi, p.se));
		add(p.se, -1); add(u, 1); modify(p.se); modify(u);
	}
}
int main(){
	n = read(), m = read();
	for(int i = 1; i < n; i++){
		int x = read(), y = read(), z = read();
		v[x].push_back(y); dis[y] = z;
	} dep[1] = 1; dfs(1); dfs2(1, 1);
	t2.build(1, 1, n); t3.build(1, 1, n);
	for(int i = 1; i <= m; i++){
		int op = read(), u = read(), v = read();
		if(op == 1) Mine(u, v - dis[u]);
		if(op == 2) Gold(u, v + dis[u]);
		cout << ans << '\n';
	} return 0;
}

「LibreOJ NOI Round #2」不等关系
首先有状压 f i , S f_{i,S} fi,S 表示选的集合为 S S S,最后一个点为 i i i 的方案数
考虑到选了哪些点并没有关系,我们只需要维护相对大小
f i , j f_{i,j} fi,j 表示到第 i i i个点,排名为 j j j 的方案数,每次填入 j j j 过后将原来排名 > = j >=j >=j 的全部加1
< < < f i , j = ∑ k = 1 j − 1 f i − 1 , k f_{i,j}=\sum_{k=1}^{j-1}f_{i-1,k} fi,j=k=1j1fi1,k
> > > f i , j = ∑ k = j i − 1 f i − 1 , k f_{i,j}=\sum_{k=j}^{i-1}f_{i-1,k} fi,j=k=ji1fi1,k
前缀和优化转移即可
这个方法好像不太能优化,考虑容斥
先保证 < < < 忽略 > > >,然后把不满足 > > > 的容斥掉
考虑到最后大于的情况是 . . . > . . . > . . . > . . . > . . . ... > ... >...>...>... ...>...>...>...>...
如果我们令满足限制为 1,不满足为 0
求的是 11111... 11111... 11111... 的方案数
考虑到 > > > 的限制不好满足,但这种方案很好算 ,就是 . . . > . . . > . . . ? . . . > . . . > . . . ...>...>...?...>...>... ...>...>...?...>...>...
这样的话 ? ? ? 前面和 ? ? ? 后面就可以没有干扰
11111 = 1111 ? − 11110 = 1111 ? − ( 111 ? 0 − 11100 ) = 1111 ? − 111 ? 0 + 11 ? 00 − 11000 11111=1111?-11110=1111?-(111?0-11100)=1111?-111?0+11?00-11000 11111=1111?11110=1111?(111?011100)=1111?111?0+11?0011000
枚举 ? ? ? 的位置 j j j,令 f i f_i fi 为 i 的方案数,位置 j j j 前面的方案数就是 f j f_j fj
然后要强制后面的全部是 0,就只有唯一的一种单调上升的排列
然而前 j 个的方案数只是一种相对顺序,i 的方案中还要对前 j 个重新分配标号
c n t i cnt_i cnti 表示 i i i 的前缀 > > > 出现次数
f i = ∑ j = 0 i − 1 f j ( i j ) ( − 1 ) c n t i − 1 − c n t j f_i=\sum_{j=0}^{i-1}f_j\binom{i}{j}(-1)^{cnt_{i-1}-cnt{j}} fi=j=0i1fj(ji)(1)cnti1cntj
组合数拆出来分治 N T T NTT NTT 即可
主要思想: > > > 分界处的条件不好处理,我们直接把它钦定为 ? ? ?,然后容斥减去不合法的方案

#include<bits/stdc++.h>
#define N 100050
using namespace std;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
	while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
	return cnt * f;
}
typedef long long ll; 
const int Mod = 998244353, G = 3;
const int C = 19;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b;}
int mul(int a, int b){ return 1ll * a * b % Mod;}
void Add(int &a, int b){ a = a + b >= Mod ? a + b - Mod : a + b;}
int power(int a, int b){ int ans = 1; for(;b;b>>=1, a=mul(a,a)) if(b&1) ans=mul(ans,a); return ans;}
int n; char S[N];
#define poly vector<int>
poly w[C + 1];
int fac[N], inv[N], ifac[N], f[N];
void prework(){
	for(int i = 1; i <= C; i++) w[i].resize(1 << i-1);
	int wn = power(G, (Mod-1) / (1<<C));
	w[C][0] = 1;
	for(int i = 1; i < (1<<C-1); i++) w[C][i] = mul(wn, w[C][i-1]);
	for(int i = C-1; i; i--) for(int j = 0; j < (1 << i-1); j++) w[i][j] = w[i+1][j << 1];
	fac[0] = fac[1] = inv[0] = inv[1] = ifac[0] = ifac[1] = 1;
	for(int i = 2; i <= n; i++){
		fac[i] = mul(fac[i-1], i); 
		inv[i] = mul(Mod-Mod/i, inv[Mod%i]);
		ifac[i] = mul(ifac[i-1], inv[i]);
	}
}
int rev[N << 4], bit, up;
void init(int len){ bit = 0; up = 1; while(up < len) up <<= 1, bit++;
	for(int i = 0; i < up; i++) rev[i] = (rev[i>>1]>>1) | ((i&1) << (bit-1));
}
int cnt[N];
void NTT(poly &a, int flg){
	for(int i = 0; i < up; i++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 1, l = 1; i < up; i <<= 1, ++l)
		for(int j = 0; j < up; j += (i<<1))	
			for(int k = 0; k < i; k++){
				int x = a[k+j], y = mul(w[l][k], a[k+j+i]);
				a[k+j] = add(x, y); a[k+j+i] = add(x, Mod-y);
			}
	if(flg == -1){
		reverse(a.begin() + 1, a.end()); int iv = power(up, Mod - 2);
		for(int i = 0; i < up; i++) a[i] = mul(a[i], iv);
	}
}
poly operator * (poly a, poly b){
	int len = a.size() + b.size() - 1;
	init(len); a.resize(up); b.resize(up);
	NTT(a, 1); NTT(b, 1);
	for(int i = 0; i < up; i++) a[i] = mul(a[i], b[i]);
	NTT(a, -1); a.resize(len); return a;
}
#define pb push_back
void cdq(int l, int r){
	if(l == r) return;
	int mid = (l+r) >> 1;
	cdq(l, mid);
	poly a, b;
	a.pb(0); b.pb(0);
	for(int i = 1; i <= r-l+1; i++) a.pb(ifac[i]);
	for(int i = l; i <= mid; i++) b.pb((S[i] == '<') ? 0 : ((cnt[i] & 1) ? Mod - f[i] : f[i]));
	a = a * b;
	for(int i = mid + 1; i <= r; i++)
		Add(f[i], mul(((cnt[i-1] & 1) ? Mod - 1: 1), a[i-l+1]));
	cdq(mid + 1, r);
}
int main(){
	scanf("%s", S + 1);
	n = strlen(S + 1) + 1;
	for(int i = 1; i < n; i++) cnt[i] = cnt[i-1] + (S[i] == '>');
	prework(); f[0] = 1; cdq(0, n);	
	cout << mul(f[n], fac[n]); return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

FSYo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值