数算期中考试复习——典型作业题

1. 因数分解

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int count(int n, int last_number) {
    if (n == 1) return 1;
    int re = 0, i;
    for (i = last_number; i <= n; i++)
        if (n % i == 0)
            re += count(n / i, i);//为什么是i?因为小于i的因数的分解数都在之前被加到re里面去了!
    return re;
}

int main() {
    int testcases;
    int n;
    scanf("%d", &testcases);
    while (testcases--) {
        scanf("%d", &n);
        printf("%d\n", count(n, 2));
    }
}

//20 = 2 * 2 * 5
//20 = 2 * 10
//20 = 4 * 5
//20 = 20

//count(10,2)
//  --count(5,2)
//      --count(1,5)=1
//  --count(2,5)=0
//  --count(1,10)=1
//count(5,4)
//  --count(1,5)=1
//count(4,5)=0
//count(2,10)=0
//count(1,20)=1

2. 抓住那头牛

描述
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:

1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟

假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?

输入
两个整数,N和K
输出
一个整数,农夫抓到牛所要花费的最小分钟数
样例输入
5 17
样例输出
4

//助教代码
#include<cstdio>
#include<cstring>
using namespace std;

const int MAX = 300002;
bool isTrodden[MAX];
int timer;

// queue
struct Record{
	int pos;
	int time;
}record[MAX] = {0};

// head and tail of queue
int head,tail;

int BFS(int target){
	int cur_pos,cur_time;
	while(head < tail){
		//Deal with head Node
		cur_pos = record[head].pos;
		cur_time = record[head].time;

		//1.Try Move right
		//Mind: If the cow is on the left, don't bother
		//没来过
		if(target > cur_pos && !isTrodden[cur_pos + 1]){
			if(cur_pos + 1 == target)
				return cur_time + 1;

			isTrodden[cur_pos + 1] = true;
			// push new element at tail
			record[tail].pos = cur_pos + 1;
			record[tail].time = cur_time + 1;
			++tail;
		}

		//2.Try Move left
		if(cur_pos > 1 && !isTrodden[cur_pos - 1]){
			if(cur_pos - 1 == target)
				return cur_time + 1;

			isTrodden[cur_pos - 1] = true;
			// push new element at tail
			record[tail].pos = cur_pos - 1;
			record[tail].time = cur_time + 1;
			++tail;
		}

		//3 Try Teleporting, mind range
		//3.Try Move twice 
		if(target > cur_pos && !isTrodden[cur_pos * 2]){
			if(cur_pos * 2 == target)
				return cur_time  + 1;

			isTrodden[cur_pos * 2 ] = true;
			// push new element at tail
			record[tail].pos = cur_pos * 2 ;
			record[tail].time = cur_time + 1;
			++tail;
		}
		++head;
	}
	return -1;
}

int main(){
	int n,k;
	scanf("%d%d",&n,&k);

	//the cow is at the left,no need to move rightwards
	if(k <= n){
		printf("%d\n",n - k);
		return 0;
	}

	//Init
	memset(isTrodden,false,MAX);
	isTrodden[n] = true;   //this place has been occupied
	record[0].pos = n,record[0].time = 0;
	head = 0,tail = 1;

	printf("%d\n",BFS(k));
	return 0;
}

3. 实现KMP

总时间限制: 1000ms 内存限制: 65535kB
描述
给两个字符串A、B, 从A中找出第一次出现B的位置。

输入
第一行输入一个整数t,表示测试数据的个数

对于每组测试数据,输入两个字符串S T,S和T中间用一个空格隔开,每组数据占一行。

S,T的长度均不超过20000
输出
对于每组测试数据,输出A中找出第一次出现B的位置,如果A不包含B,输出-1
样例输入
3
AAAAbAA Ab
AAABBB BB
XXXXXX YY
样例输出
3
3
-1
提示
使用KMP快速匹配算法能解决本题。

#include <bits/stdc++.h>
using namespace std;
int* Next(string P) {
	int m = P.length();
	int* N = new int[m];//N[i]代表的是第i个字符的特征值,代表的是P[0]~P[i]这个串的最长前缀子串的长度
	N[0] = 0;
	for (int i = 1; i < m; i++) {
		int k = N[i - 1];//default: k=0
		while (k > 0 && P[i] != P[k])
			k = N[k - 1];
		if (P[i] == P[k])
			N[i] = k + 1;
		else N[i] = 0;
	}
	return N;
}
int KMPFind(string S, string P, int* N, int startIndex = 0) {//default: startIndex=0
	int lastIndex = S.length() - P.length();
	if (startIndex > lastIndex)return -1;
	int j = 0;
	for (int i = startIndex; i < S.length(); i++) {
		while (S[i] != P[j] && j > 0)
			j = N[j - 1];
		if (S[i] == P[j])j++;
		if (j == P.length())return i - j + 1;
	}
	return -1;
}
int main() {
	int t;
	cin >> t;
	while (t--) {
		string S, P;
		cin >> S >> P;
		cout << KMPFind(S, P, Next(P), 0) << endl;
	}
	return 0;
}

4. 前缀和后缀

  • 总时间限制:

    1000ms

  • 内存限制:

    65536kB

  • 描述

    编写一个程序,当给定字符串s1和s2时,求最长的s1前缀字符串,使得它同时是s2的后缀。

  • 输入

    (多组数据) 输入包含两行。第一行包含s1,第二行包含s2。 字符串均为小写字母构成

  • 输出

    输出由一行组成,首先是一个字符串,该字符串是s1的前缀和s2的后缀,空格后跟该字符串的长度。如果最长的字符串是空字符串,则输出应直接为0. s1和s2的长度最多为50000。

  • 样例输入
    clinton homer riemann marjorie

  • 样例输出
    0 rie 3

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 5e4 + 10;
    int lens1, lens2, Next[N];
    char s1[N], s2[N];
    
    void GetNext(){
        int i, j;
        Next[0] = -1;
        i = 0;
        j = -1;
        while (i < lens1) {
            if (j == -1 || s1[i] == s1[j])
                Next[++i] = ++j;
            else
                j = Next[j];
        }
    }
    
    void Kmp() {
        int i, j;
        i = 0; j = 0;
        while (i < lens2)  {
            if (j == -1 || s1[j] == s2[i])  {
                //s2是主串
                j++;
                i++;
            }
            else
                j = Next[j];
        }
        if (!j)
            cout << 0 << endl;
        else  {
            for (int i = 0; i < j; i++)cout << s1[i];
            cout << ' ' << j << endl;
        }
    }
    
    int main() {
        while (~scanf("%s%s", s1, s2)) {
            lens1 = strlen(s1);
            lens2 = strlen(s2);
            GetNext();
            Kmp();
        }
        return 0;
    }
    

5. 字符乘方

  • 总时间限制:

    3000ms

  • 内存限制:

    65536kB

  • 描述

    给定两个字符串a和b,我们定义ab为他们的连接。例如,如果a=”abc” 而b=”def”, 则ab=”abcdef”。 如果我们将连接考虑成乘法,一个非负整数的乘方将用一种通常的方式定义:a0=””(空字符串),a(n+1)=a*(a^n)。

  • 输入

    每一个测试样例是一行可打印的字符作为输入,用s表示。s的长度至少为1,且不会超过一百万。最后的测试样例后面将是一个点号作为一行。

  • 输出

    对于每一个s,你应该打印最大的n,使得存在一个a,让s=a^n

  • 样例输入

    abcd

    aaaa

    ababab

    .

  • 样例输出

    1 4 3

  • 提示

    本问题输入量很大,请用scanf代替cin,从而避免超时。

  • 来源

    Waterloo local 2002.07.01

    #include <bits/stdc++.h>
    using namespace std;
    //最大前缀子串,包含了最多的最小循环节
    //那么总串减去最长前缀子串,得到的后缀就是最小循环节,如果长度是最小循环节的长度的整数倍
    char s[1000010];
    int Next[1000010];
    void GetNext() {
    	int j = -1;
    	int i = 0;
    	Next[0] = -1;
    	while (i < strlen(s)) {
    		if (j == -1 || s[i] == s[j]) {
    			Next[++i] = ++j;
    		}
    		else j = Next[j];
    	}
    }
    int main() {
    	while (1) {
    		memset(s, NULL, strlen(s));
    		scanf("%s", s);
    		if (!strcmp(s,".\0"))return 0;//这里有一点更改;两个字符串完全相等就会返回0
    		GetNext();
    		int len = strlen(s);
    		if (len % (len - Next[len]) == 0)cout << len / (len - Next[len]) << endl;
    		else cout << 1 << endl;
    	}
    }
    

tips:C 库函数 - memset()

描述

C 库函数 void *memset(void *str, int c, size_t n) 复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。

声明

下面是 memset() 函数的声明。

void *memset(void *str, int c, size_t n)

参数

  • str – 指向要填充的内存块。
  • c – 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
  • n – 要被设置为该值的字节数。

返回值

该值返回一个指向存储区 str 的指针。

实例

下面的实例演示了 memset() 函数的用法。

#include <stdio.h>
#include <string.h>

int main ()
{
   char str[50];

   strcpy(str,"This is string.h library function");
   puts(str);

   memset(str,'$',7);
   puts(str);
   
   return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

This is string.h library function
$$$$$$$ string.h library function

注意其他未涉及到的部分不会改变!也不会变成0或者null啥的。

6. 剪花布条

  • 总时间限制:

    1000ms

  • 内存限制:

    65536kB

  • 描述

    一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?

  • 输入

    输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。

  • 输出

    输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就输出0,每个结果之间应换行。

  • 样例输入

    abcde a3

    aaaaaa aa

    #

  • 样例输出

    0

    3

  • 来源

    HDU

#include <bits/stdc++.h>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
int nexta[1006];
char t[1006], s[1006];
void getnexta(char s[])
{
    memset(nexta, 0, sizeof(nexta));//清零
    int k = -1, j = 0;
    nexta[0] = -1;
    while (j < strlen(s))
    {
        if (k == -1 || s[j] == s[k])
            nexta[++j] = ++k;
        else k = nexta[k];
    }
}
int kmp(char s[], char t[]){//t模式串,s母串
    getnexta(t);
    int ans = 0;
    int n = strlen(s), m = strlen(t);
    int i = 0, j = 0;
    while (i < n && j < m) {
        if (j == -1 || s[i] == t[j]) {
            i++;
            j++;
        }
        else
            j = nexta[j];
        if (j == m){//根据题目要求改变  
            ans++;
            j = 0;
        }
    }
    return ans;
}
int main()
{
    while (1)
    {
        scanf("%s", s);
        if (strcmp(s, "#") == 0)
            return 0;
        scanf("%s", t);
        printf("%d\n", kmp(s, t));
    }
}

7. 中缀表达式的值

  • 总时间限制:

    200ms

  • 内存限制:

    1024kB

  • 描述

    人们熟悉的四则运算表达式称为中缀表达式,例如(23+34*45/(5+6+7))。在程序设计语言中,可以利用堆栈的方法把中缀表达式转换成保值的后缀表达式(又称逆波兰表示法),并最终变为计算机可以直接执行的指令,得到表达式的值。 给定一个中缀表达式,编写程序,利用堆栈的方法,计算表达式的值。

  • 输入

    第一行为测试数据的组数N 接下来的N行,每行是一个中缀表达式。表达式中只含数字、四则运算符和圆括号,操作数都是正整数,数和运算符、括号之间没有空格。中缀表达式的字符串长度不超过600。

  • 输出

    对每一组测试数据输出一行,为表达式的值

  • 样例输入

    3 3+5*8 (3+5)*8 (23+34*45/(5+6+7))

  • 样例输出

    43 64 108

  • 提示

    注意:运算过程均为整数运算(除法运算’/'即按照C++定义的int除以int的结果,测试数据不会出现除数为0的情况),输出结果也为整数(可能为负)。 中间计算结果可能为负。

#include<bits/stdc++.h>
using namespace std;

//定义优先级
const int END = -1;
const int VALUE = 0;
const int PLUS_MINUS = 1;
const int MULTI_DIV = 2;
const int OPEN_PAREN = 3;
const int CLOSE_PAREN = 4;

//定义符号对象的优先级
int priority(const char c) {
    switch (c) {
    case '\0':return END;
    case '+':
    case '-':return PLUS_MINUS;
    case '*':
    case '/':return MULTI_DIV;
    case '(':return OPEN_PAREN;
    case ')':return CLOSE_PAREN;
    default: return VALUE;
    }
}

struct NODE {
    int type = 0;// 栈里的元素类型, 0代表运算符, 1代表浮点数,默认为运算符,因为需要处理的大部分都是运算符
    char op = '\0';
    int number = 0;
};

NODE calc(int a, int b, char op) {
    int re = 0;
    switch (op) {
    case '+': re = a + b; break;
    case '-': re = a - b; break;
    case '*': re = a * b; break;
    case '/': re = a / b; break;
    }
    NODE result;
    result.number = re;
    result.type = 1;
    return result;
}

stack<NODE>opStack;//存储运算符的临时栈,在生成后缀表达式的过程中会全部压入postFixStack中;只有运算符
stack<NODE>postFixStack;//后缀表达式;运算符和数值都有
stack<NODE>reverseStack;//后缀表达式反过来,这样不断弹出就相当于是从左往右扫描后缀表达式;运算符和数值都有
stack<NODE>answerStack;//用于计算和存储后缀表达式中间结果的栈;只有数值
//因为在每个循环里面每个栈都会排空,所以可以放在外面,不用每次循环都重新开辟储存空间

int main() {
    int N;
    cin >> N;
    while (N--) {        
        char s[605] = "\0";//注意是双引号
        cin >> s;
        char* p, * q;
        p = q = s;
        int curPriority;
        /**********生成后缀表达式**********/
        while (1) {
            curPriority = priority(*p);
            NODE tmp;
            if (curPriority == END) {
                while (!opStack.empty()) {//符号栈剩下的符号全部弹出
                    postFixStack.push(opStack.top());
                    opStack.pop();
                }
                break;
            }
            if (curPriority == VALUE) {
                char numStr[605] = {};
                int i = 0;
                for (q = p; priority(*q) == VALUE; q++) {
                    //使用指针q进行搜索,直到q指向下一个符号或字符串末尾为止,同时将这一段数字储存在字符串中,这是为了处理两位及以上的数
                    numStr[i++] = *q;
                    numStr[i] = '\0';
                }
                tmp.number = atoi(numStr);//转换为整数
                tmp.type = 1;
                postFixStack.push(tmp);
                p = q;//转到下一个符号(或者末尾)
            }
            else if (curPriority == OPEN_PAREN) {//左括号,压入符号栈
                tmp.op = '(';
                opStack.push(tmp);
                p++;
            }
            else if (curPriority == CLOSE_PAREN) {//右括号,不断弹出直到遇到左括号
                while (!opStack.empty()) {//其实也可以换成while(1),因为必然会遇到左括号(如果输入符合规范),但是万一不规范while(1)就有死循环的风险
                    if (opStack.top().op == '(') {
                        opStack.pop();
                        break;
                    }                
                    postFixStack.push(opStack.top());
                    opStack.pop();
                }
                p++;
            }
            
            else {
                //如果栈顶的四则运算符的优先级比当前运算符优先级高、或者相等(3 - 2 + 1应该转换为3 2 - 1 +),则将栈顶的弹出
                //但是满足栈顶优先级大于当前优先级的还有栈顶为左括号的情况,这个时候不能将左括号弹出(左括号需要等到遇到右括号的时候再处理)
                //不可能遇到右括号,因为右括号根本不会入栈,一遇到右括号就全部弹出直至遇见左括号了
                //当然,前提是非空
                while (!opStack.empty() && priority(opStack.top().op) >= curPriority && priority(opStack.top().op)!= OPEN_PAREN) {                    
                    postFixStack.push(opStack.top());
                    opStack.pop();
                }
                /*
                原来的语句:
                 while (!opStack.empty()&& priority(opStack.top()) >= curPriority && priority(opStack.top()!= OPEN_PAREN))
                 知道哪里错了吗?
                 是...priority(opStack.top()【)】!= OPEN_PAREN【)】而不是...priority(opStack.top()!= OPEN_PAREN【))】!!!
                 这样会导致这一句永远是priority(1)/逻辑0而不执行循环了
                */
                tmp.op = *p;
                opStack.push(tmp);
                p++;
            }
        }
        /**********反转后缀表达式**********/
        while (!postFixStack.empty()) {                      
            reverseStack.push(postFixStack.top());
            postFixStack.pop();         
        }
        /**********计算后缀表达式的值**********/
        while (!reverseStack.empty()) {
            NODE tmp = reverseStack.top();            
            reverseStack.pop();
            if (!tmp.type) {//如果tmp是字符
                NODE topNum = answerStack.top();//答案栈栈顶的数字
                answerStack.pop();
                NODE nextTopNum = answerStack.top();//次顶的数字;这要求次顶的数字必须存在,即后缀表达式扫描到运算符时,前面至少有两个数字
                answerStack.pop();
                char ope = tmp.op;
                NODE result = calc(nextTopNum.number, topNum.number, ope);//注意次序,是【次顶 ope 栈顶】(4 5 -应为4-5)
                answerStack.push(result);
            }
            else
                answerStack.push(tmp);
        }        
        cout <<answerStack.top().number<< endl;
        while(!answerStack.empty())//其实只有一个数了,但是以防万一还是尽量排空比较好,防止影响到下一次循环
            answerStack.pop();
    }
    return 0;
}

8. 走迷宫

总时间限制: 1000ms 内存限制: 65536kB

  • 描述

    一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。
    给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。

  • 输入
    第一行是两个整数,R和C,代表迷宫的长和宽。( 1<= R,C <= 40)
    接下来是R行,每行C个字符,代表整个迷宫。
    空地格子用’.‘表示,有障碍物的格子用’#‘表示。
    迷宫左上角和右下角都是’.’。

  • 输出
    输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。计算步数要包括起点和终点。

  • 样例输入
    5 5
    …###
    #…
    #.#.#
    #.#.#
    #.#…

  • 样例输出
    9

//增加了一点注释
#include<bits/stdc++.h>
using namespace std;
char maze[50][50] = {};
int row, col;
struct NODE {
    int mRow = 1;
    int mCol = 1;
    int steps = 1;
};
//与节点有关的函数
void markNode(NODE currPoint) {
    maze[currPoint.mRow][currPoint.mCol] = 'x';//. not visited, # walls, x visited.虽说x和#也不需要区分
}
NODE asideNode(NODE currPoint,int i) {
    NODE tmp;
    switch (i)
    {
    case 1://left
        tmp.mRow = currPoint.mRow;
        tmp.mCol = currPoint.mCol - 1;
        return tmp;
    case 2://right
        tmp.mRow = currPoint.mRow;
        tmp.mCol = currPoint.mCol + 1;
        return tmp;
    case 3://down
        tmp.mRow = currPoint.mRow + 1;
        tmp.mCol = currPoint.mCol;
        return tmp;
    case 4://up
        tmp.mRow = currPoint.mRow - 1;
        tmp.mCol = currPoint.mCol;
        return tmp;
    default:
        cout << "SOMETHING WRONG" << endl;
        return currPoint;
    }    
}
int isUnvisited(NODE currPoint) {
    if (maze[currPoint.mRow][currPoint.mCol] == '.')return 1;
    return 0;
}
//可以走的节点,在循环过程中会不断抛弃老节点(pop),更新“路径进展”(push),即使有多条路径可以到达终点,也会是更短的那条先遇到/出队列
queue<NODE>validNodes;
int main() {
    //输入,构建迷宫
    cin >> row >> col;
    for (int i = 0; i <= row + 1; i++) {
        for (int j = 0; j <= col + 1; j++) {
            if (i == 0 || i == row + 1)
                maze[i][j] = '#';//把边界外的一圈都标记为#,省略判断是否越界
            else if (j == 0 || j == col + 1)
                maze[i][j] = '#';
            else
                cin >> maze[i][j];
        }
    }
    //使用队列判断
    NODE startPoint;
    markNode(startPoint);
    validNodes.push(startPoint);
    while (!validNodes.empty()) {//比while(1)要好一些
        NODE currPoint = validNodes.front();
        validNodes.pop();
        for (int i = 1; i <= 4; i++) {//左右下上
            NODE tmp = asideNode(currPoint, i);
            if (tmp.mCol == col && tmp.mRow == row) {//出口
                cout << currPoint.steps + 1 << endl;
                return 0;
            }
            if (isUnvisited(tmp)) {
                markNode(tmp);
                tmp.steps = currPoint.steps + 1;
                validNodes.push(tmp);
            }
        }
    }
    cout << "NO RIGHT PATH!" << endl;//如果没有在循环里面结束程序,那么说明没有能够到达终点的路径
    return 0;
}

9. 由中根序列和后根序列重建二叉树

  • 总时间限制:

    500ms

  • 内存限制:

    65535kB

  • 描述

    我们知道如何按照三种深度优先次序来周游一棵二叉树,来得到中根序列、前根序列和后根序列。反过来,如果给定二叉树的中根序列和后根序列,或者给定中根序列和前根序列,可以重建一二叉树。本题输入一棵二叉树的中根序列和后根序列,要求在内存中重建二叉树,最后输出这棵二叉树的前根序列。用不同的整数来唯一标识二叉树的每一个结点,下面的二叉树img 中根序列是9 5 32 67后根序列9 32 67 5前根序列5 9 67 32

  • 输入

    两行。第一行是二叉树的中根序列,第二行是后根序列。每个数字表示的结点之间用空格隔开。结点数字范围0~65535。暂不必考虑不合理的输入数据。

  • 输出

    一行。由输入中的中根序列和后根序列重建的二叉树的前根序列。每个数字表示的结点之间用空格隔开。

  • 样例输入

    9 5 32 67

    9 32 67 5

  • 样例输出

    5 9 67 32

#include <bits/stdc++.h>
using namespace std;
vector<int> a;
void find(int* ldr, int* lrd,int len) {//找到根节点,前序输出
    if (len >= 1)
        cout << lrd[len - 1] << " ";//输出后根序列的末端,即根节点
    if (len > 1)
        for (int i = 0; i < len; i++) {
            if (ldr[i] == lrd[len - 1]) {//中根序列中,根节点左边的是左节点,右边是右节点
                find(ldr, lrd, i);
                find(ldr + i + 1, lrd + i, len - i - 1);
                return;
            }
        }
}
int main() {
    int len;
    int* lrd, * ldr;
    int t;
    while (cin>>t) {
        a.push_back(t);
    }
    len = a.size() / 2;
    ldr = a.data();
    lrd = a.data() + len;
    find(ldr, lrd, len);
    return 0;
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值