CSP刷题记录

寒假闲来无事刷刷CSP的题

202012-4 食材运输

原题地址
首先,看到最大值的最小,第一反应是二分。然后就是怎么求最大值,显然是所有路径之和*2-最长的那条。
二分一个时间,可以得到哪些点满足哪种食材。用状态压缩来存储,通过状压DP来维护。
代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
#define maxn 101
int n, m, k, fr;
int dp[maxn][maxn], re[maxn][12], mmp[maxn][maxn][12], kg[maxn][12];
int nxt[210], head[maxn], tt[210], val[210], tot = 0, qt[maxn];
int lz, ss[maxn][maxn][12];
void addg(int a, int b, int c)
{
    tt[++tot] = b;
    nxt[tot] = head[a];
    val[tot] = c;
    head[a] = tot;
}

void dfs(int x, int f)
{
    int i;
    for (i = head[x]; i; i = nxt[i])
    {
        int tx = tt[i];
        if (tx == f) continue;
        dp[fr][tx] = dp[fr][x] + val[i];
        dfs(tx, x);
    }
}

int skg(int x, int k, int f)
{
    int i, j, r;
    for (i = head[x]; i; i = nxt[i])
    {
        int tx = tt[i];
        if (tx == f) continue;
        if (re[tx][k] == 1) ss[fr][tx][k] = 1;
        int u = skg(tx, k, x);
        if (ss[fr][tx][k] == 1)
        {
            mmp[fr][x][k] = mmp[fr][x][k] + u + val[i];
            ss[fr][x][k] = 1;
        }
    }
    return mmp[fr][x][k];
}

void bl(int x, int k)
{
    int i, j;
    for(i = 1; i <= n; i++)
    {
        if (kg[i][k] <= x) qt[i] = qt[i] + (1 << (k - 1));
    }
}

int qq[maxn][1024];

bool check(int x)
{
    memset(qt, 0, sizeof(qt));
    int i, j;
    for (i = 1; i <= k; i++)
    {
        bl(x, i);
    }

    int lim = (1 << k) - 1;
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= lim; j++)
            qq[i][j] = 1e9;
    }
    qq[1][qt[1]] = 1;
    for (i = 2; i <= n; i++)
    {
        qq[i][qt[i]] = 1;
        for (j = 1; j <= lim; j++)
        {
            if (qq[i - 1][j] == 1e9) continue;
            else
            {
                int tx = qt[i] | j;
                qq[i][tx] = min(qq[i - 1][tx], qq[i - 1][j] + 1);
                qq[i][j] = min(qq[i][j], qq[i - 1][j]);//这里不能少,WA+1
            }
        }
    }
    if (qq[n][lim] > m) return false;
    return true;
}

int main() 
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int i, j, a, b, c, r;
    cin >> n >> m >> k;
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= k; j++)
        {
            cin >> re[i][j];
        }
    }
    for (i = 1; i < n; i++)
    {
        cin >> a >> b >> c;
        addg(a, b, c);
        addg(b, a, c);
    }
    for (i = 1; i <= n; i++)
    {
        fr = i;
        dfs(i, 0);
        for (j = 1; j <= k; j++)
        {
            lz = 0;
            skg(i, j, 0);
            for (r = 1; r <= n; r++)
            {
                if (re[r][j]) lz = max(lz, dp[i][r]);
            }
            kg[i][j] = mmp[i][i][j] * 2 - lz;
        }
    }
    int l = 0, rt = 1e9, mid;//rt的值一开始给的n*n,贡献了一个WA
    while (l < rt - 1)//二分还是用的最古老的版本
    {
        mid = (l + rt + 1) / 2;
        if (!check(mid)) l = mid;
        else rt = mid;
    }
    if (check(l)) mid = l;
    else mid = rt;
    cout << mid << endl;
    return 0;
}

201890-3

神tm大模拟,只拿了70,调了一上午也没发现哪的问题,看来csp先4后3为妙。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
#define maxn 101
int n, m;
map<string, vector<int> >mmp, dd;
vector<int>qq[maxn];
int fa[maxn], dep[maxn];
string str[maxn], di[maxn], ss[maxn], qur;
void dfs(int x)
{
    for (int i = 0; i < str[x].length(); i++)
    {
        if (str[x][i * 2] != '.')
        {
            dep[x] = i;
            break;
        }
    }
    for (int i = dep[x] * 2; i < str[x].length(); i++)
    {
        if (str[x][i] == '#')
        {
            ss[x] = str[x].substr(dep[x] * 2, i - dep[x] * 2 - 1);
            di[x] = str[x].substr(i, str[x].length() - i);
            break;
        }
    }
    if (ss[x].length() == 0) ss[x] = str[x].substr(dep[x] * 2, str[x].length() - dep[x] * 2);
    if (di[x].length()) dd[di[x]].push_back(x);
    mmp[ss[x]].push_back(x);
    for (int i = x - 1; i >= 1; i--)
    {
        if (dep[x] == dep[i])
        {
            fa[x] = fa[i];
            qq[fa[i]].push_back(x);
            break;
        }
        if (dep[x] == dep[i] + 1)
        {
            fa[x] = i;
            qq[i].push_back(x);
            break;
        }
    }
}

int check()
{
    if (qur[0] == '#') return 2;
    for (int i = 0; i < qur.length(); i++)
    {
        if (qur[i] == ' ') return 3;
    }
    return 1;
}

void solve2()
{
    int ans = dd[qur].size();
    cout << ans;
    for (int i = 0; i < ans; i++)
    {
        cout << ' ' << dd[qur][i];
    }
    cout << endl;
}

void solve1()
{
    int ans = mmp[qur].size();
    cout << ans;
    for (int i = 0; i < ans; i++)
    {
        cout << ' ' << mmp[qur][i];
    }
    cout << endl;
}

vector<string>rr;
vector<int>uu;
void fnd(int x, int dk)
{
    for (int i = 0; i < qq[x].size(); i++)
    {
        int tx = qq[x][i];
        if (rr[dk][0] != '#')
        {
            if (ss[tx].length())
            {
                if (ss[tx] == rr[dk])
                {
                    if (dk == rr.size() - 1)
                    {
                        uu.push_back(tx);
                    }
                    else fnd(tx, dk + 1);
                }
            }
        }
        else
        {
            if (di[tx].length())
            {
                if (di[tx] == rr[dk])
                {
                    if (dk == rr.size() - 1)
                    {
                        uu.push_back(tx);
                    }
                    else fnd(tx, dk + 1);
                }
            }
        }
    }
}
void solve3()
{
    int i, j, st = 0;
    rr.clear(); uu.clear();
    for (i = 0; i < qur.length(); i++)
    {
        if (qur[i] == ' ')
        {
            rr.push_back(qur.substr(st, i - st));
            st = i + 1;
        }
    }
    rr.push_back(qur.substr(st, qur.length()));
    if (rr[0][0] != '#')
    {
        for (i = 0; i < mmp[rr[0]].size(); i++)
        {
            fnd(mmp[rr[0]][i], 1);
        }
    }
    else
    {
        for (i = 0; i < dd[rr[0]].size(); i++)
        {
            fnd(dd[rr[0]][i], 1);
        }
    }
    int ans = uu.size();
    cout << ans;
    for (i = 0; i < ans; i++)
    {
        cout << ' ' << uu[i];
    }
    cout << endl;
}

int main() 
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int i, j;
    cin >> n >> m;
    cin.get();
    for (i = 1; i <= n; i++)
    {
        getline(cin, str[i]);
        dfs(i);
    }
    while (m--)
    {
        getline(cin, qur);
        int fl = check();
        if (fl == 1) solve1();
        else if (fl == 2) solve2();
        else solve3();
    }
    return 0;
}

/*
11 1
ht
..he
....ti
..bo
....h1
....p #sub
....di #mai
......h2
......p #non
......di
........p #two
di #two
*/

201909-5 城市规划

原题地址

代码:
树DP经典题,但根据参考博客调了好一会儿才调出来

#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
#define maxn 50005
#define mm 2000010
typedef long long ll;
const int mod = 998244353;
int n, m, k;
ll dp[maxn][101], kn[maxn][101], nxt[2 * maxn], head[maxn], tt[2 * maxn], tot = 0, val[2 * maxn];
int st[maxn];
int bl[maxn];
void add(int a, int b, int c)
{
    tt[++tot] = b;
    val[tot] = c;
    nxt[tot] = head[a];
    head[a] = tot;
}

void solve(int x, int f)
{
    int i, j, r;
    if (bl[x] == 1)
    {
        dp[x][1] = 0;//如果x为关键点,选不选
        st[x] = 1;
    }
    for (i = head[x]; i; i = nxt[i])
    {
        int tx = tt[i];
        if (tx == f) continue;
        solve(tx, x);
        int sum = min(k, st[x] + st[tx]), mn = min(k, st[tx]);
        ll t[101];
        //这里添加临时数组是没有注意到的,根据参考博客才加上了
        //具体原因及必要性参考参考博客
        for (j = 0; j <= k; j++) t[j] = dp[x][j];
        for (j = 1; j <= st[tx]; j++)
        {
            if (j > k) continue;//绝对不能写成>=
            for (r = 0; r <= sum - j; r++)
            {
                /*
                if (t[r + j] > dp[x][r] + r * kn[tx][j] + dp[tx][j] + j * kn[x][r] + (ll)r * j * val[i])
                {
                    t[r + j] = dp[x][r] + r * kn[tx][j] + dp[tx][j] + j * kn[x][r] + (ll)r * j * val[i];
                    kn[x][r + j] = kn[x][r] + kn[tx][j] + (ll)j * val[i];
                }
                */
                //上面是我自己推的dp转移方程,kn[x][r]代表x为根的子树选r个点,这r个点到x的距离之和,然鹅它只拿了20(加上了临时数组记录,这里略去了)
                t[r + j] = min(t[r + j], dp[x][r] + dp[tx][j] + ((ll)k - (ll)j) * 1ll * j * val[i]);
            }
        }
        for (j = 0; j <= k; j++)
        {
            dp[x][j] = t[j];
        }
        st[x] += st[tx];
    }
}

int main() 
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int i, j, r, a, b, c;
    cin >> n >> m >> k;
    for (i = 1; i <= m; i++)
    {
        cin >> a;
        bl[a] = 1;
    }
    for (i = 1; i < n; i++)
    {
        cin >> a >> b >> c;
        add(a, b, c);
        add(b, a, c);
    }
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= k; j++)
        {
            dp[i][j] = 1e18;
        }
    }
    solve(1, 0);
    cout << dp[1][k] << endl;
    return 0;
}

/*
5 3 2
1 3 5
1 2 4
1 3 5
1 4 3
4 5 1
*/

201812-3

原题地址

代码:
拿了60,以后慢慢debug吧

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
#include<stack>
#define ll long long
using namespace std;
#define maxn 100010
int n;
struct nod
{
	int a, b, c, d;
	int kl;
	ll sh;
	bool operator <(nod u)
	{
		if (sh != u.sh) return sh < u.sh;
		else return kl < u.kl;
	}
}qq[maxn];
int vis[maxn];
stack<nod>kkl, bbl;
void st(char x[], int id)//标准化
{
	int i, ct = 1, zh = 0, fl = 0;
	int len = strlen(x + 1);
	for (i = 1; i <= len; i++)
	{
		if (x[i] >= '0' && x[i] <= '9')
		{
			zh = zh * 10 + x[i] - '0';
		}
		else if (x[i] == '.')
		{
			if (ct == 1) qq[id].a = zh;
			else if (ct == 2) qq[id].b = zh;
			else qq[id].c = zh;
			zh = 0; ct++;
		}
		else if (x[i] == '/')
		{
			fl = 1;
			if (ct == 1) qq[id].a = zh;
			else if (ct == 2) qq[id].b = zh;
			else if (ct == 3) qq[id].c = zh;
			else qq[id].d = zh;
			zh = 0;
		}
	}
	if (fl) qq[id].kl = zh;
	else
	{
		if (ct == 1) qq[id].a = zh;
		else if (ct == 2) qq[id].b = zh;
		else if (ct == 3) qq[id].c = zh;
		else qq[id].d = zh;
		qq[id].kl = ct * 8;
	}
	qq[id].sh = (ll)256 * 256 * 256 * qq[id].a + 256 * 256 * qq[id].b + 256 * qq[id].c + qq[id].d;
}

void dfs(nod x)
{
	nod tw = kkl.top();
	while ((x.sh ^ tw.sh) == ((ll)1 << (32 - x.kl)) && (x.kl == tw.kl))
	{
		tw.kl--;
		kkl.pop();
		x = tw;
		if (!kkl.empty()) tw = kkl.top();
		else break;
	}
	kkl.push(x);
}


int main() 
{
	int i, j, k;
	char tw[101];
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> n;
	cin.get();
	for (i = 1; i <= n; i++)
	{
		cin >> tw + 1;
		st(tw, i);
	}
	//排序
	sort(qq + 1, qq + n + 1);
	//小到大合并
	int tot = 0;
	qq[++tot] = qq[1];
	for (i = 2; i <= n; i++)
	{
		if ((qq[i].sh ^ qq[tot].sh) <= ((ll)1 << (31 - qq[i].kl))) continue;
		else qq[++tot] = qq[i];
	}
	//同级合并
	kkl.push(qq[1]);
	for (i = 2; i <= tot; i++)
	{
		dfs(qq[i]);
	}
	//输出
	while (!kkl.empty())
	{
		nod tw = kkl.top();
		kkl.pop(); bbl.push(tw);
	}
	while (!bbl.empty())
	{
		nod tw = bbl.top();
		bbl.pop();
		cout << tw.a << '.' << tw.b << '.' << tw.c << '.' << tw.d << '/' << tw.kl << endl;
	}
	return 0;
}

/*
5
1.0.0.0/8
0.64.0.0/10
0.0.0.0/10
0.192.0.0/10
0.128.0.0/10
*/

202009-4

原题地址

代码:
题面看起来挺唬人的,其实想清楚就不难。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 2002
#define mm 2000010
typedef long long ll;
const int mod = 998244353;
const double pi = acos(-1.0);
int n, m;
double qq[maxn][101], r, st[101], dis[maxn][maxn], qis[maxn], tg[maxn];

double gd(double st[], double tt[])
{
    double tmp = 0.0;
    for (int i = 1; i <= n; i++)
    {
        tmp = tmp + (st[i] - tt[i]) * (st[i] - tt[i]);
    }
    return sqrt(tmp);
}

double gs(double a, double b, double c)
{
    double q = (a + b + c) / 2.0;
    return sqrt(q * (q - a) * (q - b) * (q - c));
}

double gcos(double a, double b, double c)
{
    double tmp = (a * a + b * b - c * c) / (2 * a * b);
    return acos(tmp);
}

int main() 
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int i, j, a, b, c;
    cin >> n >> m;
    cin >> r;
    for (i = 1; i <= n; i++)
    {
        cin >> st[i];
    }
    for (i = 1; i <= m; i++)
    {
        for (j = 1; j <= n; j++)
        {
            cin >> qq[i][j];
        }
    }
    for (i = 1; i <= m; i++)
    {
        qis[i] = gd(st, qq[i]);
        tg[i] = sqrt(qis[i] * qis[i] - r * r);
    }
    for (i = 1; i <= m; i++)
    {
        for (j = 1; j <= m; j++)
        {
            if (i == j)
            {
                dis[i][j] = 0.0;
                break;
            }
            double lk = gd(qq[i], qq[j]);
            double ts = gs(qis[i], qis[j], lk);
            double hl = 2 * ts / lk;
            if (hl >= r || qis[j] * qis[j] + lk * lk < qis[i] * qis[i] || qis[i] * qis[i] + lk * lk < qis[j] * qis[j])//这里值得关注的是考虑了线段与圆不相交的情况
            {
                dis[i][j] = lk;
                continue;
            }
            double tcg = gcos(qis[i], qis[j], lk);
            double tag = acos(r / qis[i]);
            double tbg = acos(r / qis[j]);
            double tp = tcg - tag - tbg;
            dis[i][j] = tg[i] + tg[j] + r * tp;
        }
    }

    for (i = 1; i <= m; i++)
    {
        for (j = i + 1; j <= m; j++)
        {
            dis[i][j] = dis[j][i];
        }
    }

    for (i = 1; i <= m; i++)
    {
        double ans = 0.0;
        for (j = 1; j <= m; j++)
        {
            ans = ans + dis[i][j];
        }
        printf("%.12lf\n", ans);
    }
    return 0;
}

201803-4

原题地址
代码:
最普通的暴力实现

#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 2002
#define mm 2000010
typedef long long ll;
const int mod = 998244353;
const double pi = acos(-1.0);
int qq[10], T;
int check(int x[])//检查棋盘胜负情况
{
    int i, j;
    for (i = 1; i <= 3; i++)
    {
        if (x[i * 3 - 2] == x[i * 3 - 1] && x[i * 3] == x[i * 3 - 2] && x[i * 3])
        {
            if (x[i * 3] == 1) return 1;
            else return 2;
        }
        if (x[i] == x[3 + i] && x[i + 3] == x[i + 6] && x[i])
        {
            if (x[i] == 1) return 1;
            else return 2;
        }
    }
    if (x[1] == x[5] && x[5] == x[9] && x[1])
    {
        if (x[1] == 1) return 1;
        else return 2;
    }
    if (x[3] == x[5] && x[7] == x[5] && x[3])
    {
        if (x[5] == 1) return 1;
        else return 2;
    }
    for (i = 1; i <= 9; i++)
    {
        if (x[i] == 0) return 10;
    }
    return 0;
}

int cnt(int x[])
{
    int a = 0;
    for (int i = 1; i <= 9; i++)
    {
        if (x[i] == 0) a++;
    }
    return a;
}

int dfs(int x[])
{
    int i, a = 0, b = 0, fl = 0, j, mans = -100, nans = 100;
    if (check(x) == 0)
    {
        return 0;
    }
    else if (check(x) == 1)
    {
        return cnt(x) + 1;
    }
    else if (check(x) == 2)
    {
        return -cnt(x) - 1;
    }
    for (i = 1; i <= 9; i++)
    {
        if (x[i] == 1) a++;
        else if (x[i] == 2) b++;
    }
    if (a > b) fl = 2;
    else fl = 1;
    for (i = 1; i <= 9; i++)
    {
        if (x[i] == 0)
        {
            int tt[10];
            for (j = 1; j <= 9; j++)
            {
                tt[j] = x[j];
            }
            tt[i] = fl;
            if (fl == 1)
            {
                mans = max(mans, dfs(tt));
            }
            else nans = min(nans, dfs(tt));
        }
    }
    if (fl == 1) return mans;
    return nans;
}

int main() 
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int i, j, a, b, c;
    cin >> T;
    while (T--)
    {
        for (i = 1; i <= 9; i++)
        {
            cin >> qq[i];
        }
        int ans = dfs(qq);
        cout << ans << endl;
    }
    return 0;
}

不过偶然发现了之前没看到的一个知识点:α-β剪枝
网上关于α-β剪枝的博客写的乱七八糟的很多伪代码都有问题。
剪枝的中心思想是:不需要知道比当前选择还要差的选择有多差,具体实现是预判我方选择某个点后,对方下个点会遏制我方的得分,遏制后这个得分的最大值。反之,对方预判选择一个点后,我方会尽量扩大我方得分,这个得分的最小值。
在这里插入图片描述
图片来源(但我觉得它的伪代码有点奇怪)
感觉具体实现方法解释起来太绕了,直接放代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 2002
#define mm 2000010
typedef long long ll;
const int mod = 998244353;
const double pi = acos(-1.0);
int qq[10], T;
int check(int x[])//检查棋盘胜负情况
{
    int i, j;
    for (i = 1; i <= 3; i++)
    {
        if (x[i * 3 - 2] == x[i * 3 - 1] && x[i * 3] == x[i * 3 - 2] && x[i * 3])
        {
            if (x[i * 3] == 1) return 1;
            else return 2;
        }
        if (x[i] == x[3 + i] && x[i + 3] == x[i + 6] && x[i])
        {
            if (x[i] == 1) return 1;
            else return 2;
        }
    }
    if (x[1] == x[5] && x[5] == x[9] && x[1])
    {
        if (x[1] == 1) return 1;
        else return 2;
    }
    if (x[3] == x[5] && x[7] == x[5] && x[3])
    {
        if (x[5] == 1) return 1;
        else return 2;
    }
    for (i = 1; i <= 9; i++)
    {
        if (x[i] == 0) return 10;
    }
    return 0;
}

int cnt(int x[])
{
    int a = 0;
    for (int i = 1; i <= 9; i++)
    {
        if (x[i] == 0) a++;
    }
    return a;
}

int dfs(int x[], int lev, int cur)
{
    int i, a = 0, b = 0, fl = 0, j, nans = -100, mans = 100;
    if (check(x) == 0)
    {
        return 0;
    }
    else if (check(x) == 1)
    {
        return cnt(x) + 1;
    }
    else if (check(x) == 2)
    {
        return -cnt(x) - 1;
    }
    for (i = 1; i <= 9; i++)
    {
        if (x[i] == 1) a++;
        else if (x[i] == 2) b++;
    }
    fl = (9 - lev) % 2 + 1;
    //下面模拟的是:如果选择这个点x[],对面会不会获得比当前值(cur)更优的选择
    for (i = 1; i <= 9; i++)//遍历对面可能的选择
    {
        if (x[i] == 0)
        {
            int tt[10];
            for (j = 1; j <= 9; j++)
            {
                tt[j] = x[j];
            }
            tt[i] = fl;
            if (fl == 1)
            {
                nans = max(nans, dfs(tt, lev - 1, nans));
                if (nans > cur)
                {
                    return nans;//说明这个点对于对方来说已经是个很差的点了
                }
            }
            else if (fl == 2)
            {
                mans = min(mans, dfs(tt, lev - 1, mans));
                if (mans < cur)
                {
                    return mans;//说明这个点对我方已经很差了
                }
            }
        }
    }
    if (fl == 1) return nans;
    return mans;
}

int main() 
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int i, j, a, b, c;
    cin >> T;
    while (T--)
    {
        for (i = 1; i <= 9; i++)
        {
            cin >> qq[i];
        }
        int lv = cnt(qq);
        int ans = dfs(qq, lv, 100);
        cout << ans << endl;
    }
    return 0;
}

在这里插入图片描述
运行效率较最大最小搜索有所提升

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值