第十一届蓝桥杯 决赛 部分题解 C/C++ 通俗易懂版 保证初中生和高中生能够看懂的题解

宇宙第一小正太\(^o^)/~萌量爆表求带飞=≡Σ((( つ^o^)つ~ dalao们点个关注呗~


试题:扩散

题目描述:

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小蓝在一张无限大的特殊画布上作画。

这张画布可以看成一个方格图,每个格子可以用一个二维的整数坐标表示。

小蓝在画布上首先点了一下几个点:(0,0),(2020,11),(11,14),(2000,2000)。

只有这几个格子上有黑色,其它位置都是白色的。

每过一分钟,黑色就会扩散一点。具体的,如果一个格子里面是黑色,它就会扩散到上、下、左、右四个相邻的格子中,使得这四个格子也变成黑色(如果原来就是黑色,则还是黑色)。

请问,经过 2020分钟后,画布上有多少个格子是黑色的。

解析:

做法一:这就是很典型的bfs问题。bfs是按层次搜索,而这里的层次实际上就是时间点,按照时间往后面扩散就可以了。

做法二:枚举每个坐标上的点,有没有可能被扩散到,如果能被扩散到,ans++。判断的标准是:曼哈顿距离(即两点的横坐标和纵坐标的差值的长度)。这是因为扩散的方向是上下左右,不是像墨水一样散开。

正解代码:

#include <iostream>
#include <queue>
using namespace std;
#define Max_N 10005
#define ADD 2021
typedef pair<int, int> P;
int map[Max_N][Max_N] = {0};
long long ans = 4;
int dx[5] = {0, 0, 1, -1};
int dy[5] = {-1, 1, 0, 0};
int main() {
    memset(map, -1, sizeof(map));  // map设置为-1代表没有访问过。map存放的值是:时间
    queue<P> Que;

    Que.push(P(0 + ADD, 0 + ADD));
    map[0 + ADD][0 + ADD] = 0;

    Que.push(P(2020 + ADD, 11 + ADD));
    map[2020 + ADD][11 + ADD] = 0;

    Que.push(P(11 + ADD, 14 + ADD));
    map[11 + ADD][14 + ADD] = 0;

    Que.push(P(2000 + ADD, 2000 + ADD));
    map[2000 + ADD][2000 + ADD] = 0;

    while (!Que.empty()) {
        int ix = Que.front().first, iy = Que.front().second;
        Que.pop();
        if (map[ix][iy] == 2020) {
            continue;
        }
        for (int ddt = 0; ddt < 4; ddt++) {
            int tx = ix + dx[ddt], ty = iy + dy[ddt];
            if (map[tx][ty] == -1) {
                Que.push(P(tx, ty));
                map[tx][ty] = map[ix][iy] + 1;
                ans++;
            }
        }
    }

    cout << ans << endl;
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
signed main()
{
    int ans = 0;
    for(int x = 0 - 2020 ; x <= 2020 + 2020 ; x ++)
    {
        for(int y = 0 - 2020 ; y <= 2020 + 2020 ; y ++)
        {
            if(abs(x - 0) + abs(y - 0) <= 2020 || abs(x - 2020) + abs(y - 11) <= 2020
            || abs(x - 11) + abs(y - 14) <= 2020 || abs(x - 2000) + abs(y - 2000) <= 2020)
            ans ++ ;
        }
    }
    cout << ans << '\n';
    return 0;
} 

试题:本质上升序列

题目描述:

解析:

这还是一道很今典的动态规划问题。LIS。

只不过现在要求了一句,就是本质不同。

所以需要dp数组执行一个去重的工作,什么意思呢?

我们首先想想,普通的LIS为什么会出现重复的情况。比如现在,我们有一个dp数组。

 那么dp[4]就是说以st[4]为结尾的序列的LIS的个数。

那如果在8的位置上又重复了一次n。

那么如果不进行去重的话,dp[8]就存放的个数是绿色花括号里面的结果。 

重复的是之前的dp[4]里面的存放的红色花括号里面的结果。

随意最终的正确答案是粉色花括号里面的结果。

让我们扩展一下,就会发现:如果Z无论怎么去拼接,都不会产生重复的状态。

正解代码:

#include <iostream>

using namespace std;

int dp[220];

int main()
{
    string str ="tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl";
    for(int i = 0;i<200;i++){
        dp[i] = 1;
        for(int j=0;j<i;j++){
            if(str[i]>str[j]){
                dp[i] += dp[j];
            }else if(str[i] == str [j]){
                dp[i] -= dp[j];
            }
        }
    }

    long long ans = 0;
    for(int i=0;i<200;i++){
        ans+=dp[i];
    }
    cout<<ans<<endl;
    return 0;
}

试题:玩具蛇

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小蓝有一条玩具蛇,一共有 16 节,上面标着数字 1 至 16。每一节都是一个正方形的形状。相邻的两节可以成直线或者成 90 度角。

小蓝还有一个 4 × 4的方格盒子,用于存放玩具蛇,盒子的方格上依次标着字母 A 到 P 共 16 个字母。

小蓝可以折叠自己的玩具蛇放到盒子里面。他发现,有很多种方案可以将玩具蛇放进去。

下图给出了两种方案:

图片描述

请帮小蓝计算一下,总共有多少种不同的方案。如果两个方案中,存在玩具蛇的某一节放在了盒子的不同格子里,则认为是不同的方案。

解析:

枚举每一个点,放入蛇的头部,然后再使用dfs来递归的放入其他的身体。最终计算出答案。

正解代码:

#include <iostream>
using namespace std;
int map[7][7] = {0};
long long ans = 0;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
void dfs(int x, int y, int step) {
    map[x][y] = step;
    if (step == 16) {
        ans++;
        map[x][y] = 0;  //一定注意要有这一句话。
        return;
    }
    for (int it = 0; it < 4; it++) {
        if (map[x + dx[it]][y + dy[it]] == 0 && 1 <= x + dx[it] && x + dx[it] <= 4 && 1 <= y + dy[it] && y + dy[it] <= 4) {
            dfs(x + dx[it], y + dy[it], step + 1);
        }
    }

    map[x][y] = 0;
}
int main() {
    for (int i = 1; i <= 4; i++) {
        for (int j = 1; j <= 4; j++) {
            memset(map, 0, sizeof(map));
            dfs(i, j, 1);
        }
    }
    cout << ans;
    return 0;
}

试题:皮亚诺曲线距离

题目描述:

皮亚诺曲线是一条平面内的曲线。

下图给出了皮亚诺曲线的 1 阶情形,它是从左下角出发,经过一个 3 × 3的方格中的每一个格子,最终到达右上角的一条曲线。

图片描述

下图给出了皮亚诺曲线的 2 阶情形,它是经过一个 3^2 ×3^2 的方格中的每一个格子的一条曲线。它是将 1 阶曲线的每个方格由 1 阶曲线替换而成。

图片描述

下图给出了皮亚诺曲线的 3 阶情形,它是经过一个 3^3 × 3^3 的方格中的每一个格子的一条曲线。它是将 2 阶曲线的每个方格由 1 阶曲线替换而成。

图片描述

皮亚诺曲线总是从左下角开始出发,最终到达右上角。

我们将这些格子放到坐标系中,对于 kk 阶皮亚诺曲线,左下角的坐标是(0, 0),右上角坐标是 (3^k − 1, 3^k − 1),右下角坐标是 (3^k − 1, 0),左上角坐标是(0, 3^k − 1)。

给定 k阶皮亚诺曲线上的两个点的坐标,请问这两个点之间,如果沿着皮亚诺曲线走,距离是到少?解析:

分成九个区域,每个区域其实都是从第一个区域变化来的。然后递归去变换就可以了。

红色线是分开区域的意思,分开了九个区域,绿色箭头是辅助我们去想到底是证明变换的。

谈蓝色的圆圈是标记了每个区域是怎么进入的。

黄色的是坐标轴,x和y的方向被告诉给我们了。

https://www.lanqiao.cn/courses/3981/learning/?id=134761

正解代码:

(没有考虑高精度,慎用)

#include <cmath>
#include <iostream>
using namespace std;
long long k, x1, y1_1, x2, y2;
long long GetInf(long long k, long long x, long long y) {
    long long Len = pow(3, k - 1);
    long long Lx = x / Len, Ly = y / Len;
    if (Lx == 0) {
        if (Ly == 0)
            return 1;
        if (Ly == 1)
            return 2;
        if (Ly == 2)
            return 3;
    } else if (Lx == 1) {
        if (Ly == 2)
            return 4;
        if (Ly == 1)
            return 5;
        if (Ly == 0)
            return 6;
    } else if (Lx == 2) {
        if (Ly == 0)
            return 7;
        if (Ly == 1)
            return 8;
        if (Ly == 2)
            return 9;
    }
}
long long dfs(long long k, long long x, long long y) {
    //最基础的一层
    if (k == 1) {
        if (x == 0) {
            if (y == 0)
                return 0;
            if (y == 1)
                return 1;
            if (y == 2)
                return 2;
        } else if (x == 1) {
            if (y == 2)
                return 3;
            if (y == 1)
                return 4;
            if (y == 0)
                return 5;
        } else if (x == 2) {
            if (y == 0)
                return 6;
            if (y == 1)
                return 7;
            if (y == 2)
                return 8;
        }
    }
    //查找上一层 k-1
    long long UpperTotal = pow(9, k - 1) - 1;  //上一层的所有点的距离。
    UpperTotal++;                              //考虑两个区域的连接线。
    long long Len = pow(3, k - 1);             //上一层的长度。
    long long No = GetInf(k, x, y);            //判断是上一层的第几个的转移点。
    switch (No) {
        case 1: {
            return 0 * UpperTotal + dfs(k - 1, x, y);
            break;
        }
        case 2: {
            long long X = Len - 1;  //缩放因子
            return 1 * UpperTotal + dfs(k - 1, X - (x % Len), y % Len);
            break;
        }
        case 3: {
            return 2 * UpperTotal + dfs(k - 1, x % Len, y % Len);
            break;
        }
        case 4: {
            long long Y = Len - 1;  //缩放因子
            return 3 * UpperTotal + dfs(k - 1, x % Len, Y - (y % Len));
            break;
        }
        case 5: {
            long long X = Len - 1;  //缩放因子
            long long Y = Len - 1;  //缩放因子
            return 4 * UpperTotal + dfs(k - 1, X - (x % Len), Y - (y % Len));
            break;
        }
        case 6: {
            long long Y = Len - 1;  //缩放因子
            return 5 * UpperTotal + dfs(k - 1, x % Len, Y - (y % Len));
            break;
        }
        case 7: {
            return 6 * UpperTotal + dfs(k - 1, x % Len, y % Len);
            break;
        }
        case 8: {
            long long X = Len - 1;  //缩放因子
            return 7 * UpperTotal + dfs(k - 1, X - (x % Len), y % Len);
            break;
        }
        case 9: {
            return 8 * UpperTotal + dfs(k - 1, x % Len, y % Len);
            break;
        }
    }
}
int main() {
    scanf("%lld%lld%lld%lld%lld", &k, &x1, &y1_1, &x2, &y2);
    cout << abs(dfs(k, x1, y1_1) - dfs(k, x2, y2));
    return 0;
}
#include<bits/stdc++.h>
#define ll long long
using namespace std;
template<typename T>void Out(T x)
{
    if(x < 0) putchar('-') , x = -x;
    if(x > 9) Out(x / 10);
    putchar(x % 10 + '0');
}
const int N = 40;
ll p[N];
map<pair<int , int> , int>mp;
ll calc(int n , ll x , ll y , map<pair<int , int> , int>mp)
{
    __int128 ans = 0;
    ll x_ = x / p[n] , y_ = y / p[n];
    if(!n) return mp[make_pair(x_ , y_)] - 1;
    else
    {
        ans += (mp[make_pair(x_ , y_)] - 1) * p[n] * p[n];
        map<pair<int , int> , int>mp1;
        if((x_ == 0 && y_ == 1) || (x_ == 2 && y_ == 1))
        {
            for(int i = 0 ; i <= 2 ; i ++)
            {
                for(int j = 0 ; j <= 2 ; j ++)
                    mp1[make_pair(2 - i , j)] = mp[make_pair(i , j)];
            }
        }
        else if((x_ == 1 && y_ == 2) || (x_ == 1 && y_ == 0))
        {
            for(int i = 0 ; i <= 2 ; i ++)
            {
                for(int j = 0 ; j <= 2 ; j ++)
                    mp1[make_pair(i , 2 - j)] = mp[make_pair(i , j)];
            }
        }
        else if(x_ == 1 && y_ == 1)
        {
            for(int i = 0 ; i <= 2 ; i ++)
            {
                for(int j = 0 ; j <= 2 ; j ++)
                    mp1[make_pair(2 - i , 2 - j)] = mp[make_pair(i , j)];
            }
        }
        else mp1 = mp;
        return ans += calc(n - 1 , x % p[n] , y % p[n] , mp1);
    }
}
void init()
{
    p[0] = 1;
    for(int i = 1 ; i < N ; i ++) p[i] = p[i - 1] * 3;
    mp[make_pair(0 , 0)] = 1;
    mp[make_pair(0 , 1)] = 2;
    mp[make_pair(0 , 2)] = 3;
    mp[make_pair(1 , 2)] = 4;
    mp[make_pair(1 , 1)] = 5;
    mp[make_pair(1 , 0)] = 6;
    mp[make_pair(2 , 0)] = 7;
    mp[make_pair(2 , 1)] = 8;
    mp[make_pair(2 , 2)] = 9;
}
signed main()
{
    init();
    int k ;
    ll x1 , y1 , x2 , y2;
    cin >> k >> x1 >> y1 >> x2 >> y2;
    __int128 a = calc(39 , x1 , y1 , mp);
    __int128 b = calc(39 , x2 , y2 , mp);
    if(a > b) Out(a - b);
    else Out(b - a);
    puts("");
    return 0;
}

 试题:游园安排

题目描述:

解析:


本题目是一道很典型的动态规划问题,他的模型就是最长上升子序列。LIS。
难点在于(1)这么保证字典序最小。(2)怎么去输出路径的结果。

难点分步突破:


突破(1):我们在拼接的时候可以使用贪心法。什么意思。比如现在我们有序列ab,和ac。虽然把z拼接到ab和ac的后面长度都是3,但是为了找出最小的字典序,所以我们最后还是把z拼接到了b上面。
意思就是,每次保证dp[i]的第i个字符,能拼接的这个dp[j]是所有能拼接dp[j]中字典序最小的那一个。那我怎么知道当前的i是从哪里的j接上去的呢?

突破(2):我们使用pos数组,来记录我们是从哪里的dp[j]走过来的,最后使用dfs还原路径。

# 算法证明:

对于“黄色”位置,那么“红色”位置是“黄色”能保证最长情况下可以找到的字典序最小的一个位置。
对于“蓝色”位置,那么“黄色”位置是“蓝色”能保证最长情况下可以找到的字典序最小的一个位置。
。。。

就这样,贪心保证了答案的正确性。

正解代码:

代码如下:(不一定正确,通过了蓝桥杯的样例,但它的那个样例太水了,就是数据规模太小了)

下面这个代码是我写的。O(N^2)
 

#include <cmath>
#include <iostream>
using namespace std;
int dp[100000], pos[1000000];
string st[100000] /*拆分之后的字符串*/, sst /*用来保存答案*/;
int ans = -1;
void Out(int x) {
    if (x == pos[x]) {
        cout << st[x];
        return;
    }
    Out(pos[x]);
    cout << st[x];
}

int main() {
    cin >> sst;
    int Len = 0;
    string tmp = "";
    for (int i = 0; i < sst.length(); i++) {
        tmp.push_back(sst[i]);
        if (sst[i + 1] >= 'A' && sst[i + 1] <= 'Z' || i == sst.length() - 1) {
            st[Len++] = tmp;
            tmp.clear();
        }
    }

    for (int i = 0; i < Len; i++) {
        dp[i] = 1;
        pos[i] = i;
        //开始拼接LIS。
        for (int j = 0; j < i; j++) {
            //可以拼接,然后长度可以更长。
            if (st[i] > st[j] && dp[j] + 1 > dp[i]) {
                dp[i] = dp[j] + 1;
                pos[i] = j;
            }
            //可以拼接,长度是一样的,但是字典序可以更小。
            if (st[i] > st[j] && dp[j] + 1 == dp[i] && st[j] < st[pos[i]]) {
                pos[i] = j;
            }
        }
    }

    int F_I = 0;
    for (int i = 1; i < Len; i++) {
        if (dp[i] > dp[F_I]) {
            F_I = i;
        }
        if (dp[i] == dp[F_I] && st[i] < st[F_I]) {
            F_I = i;
        }
    }

    Out(F_I);

    return 0;
}

本题还有一种做法是O(NLogN)的做法,请看官方题解(需要9.9元):https://www.lanqiao.cn/courses/3981/learning/?id=134762

我在这里大致讲一讲它的想法:

首先你要掌握LIS的O(NLogN)的做法的原理。其中LogN从N的复杂度降下是因为使用了一个优先队列来优化。

具体参考lxt-Lucia小仙女的这篇文章的解法二:https://blog.csdn.net/lxt_Lucia/article/details/81206439

好,现在我假定您已经会了使用NLogN做LIS的解法。那么现在首先问问自己,为什么使用了这个解法就能保证字典序是最小的呢?

如果您不能准确的告诉小熊,小熊建议您再次把上文的链接读一遍。如果您知道了答案,那很好。它保证了字典序最小的原理其实就是因为每次都会使用s[i]来更新生成的dp(LIS序列)。

另外,dp数组保存的是最终得到的LIS序列的答案吗?

别搞错,dp[N]存放的是N长度的LIS的末尾位置。

那我们怎么还原出这个LIS的样貌呢?

方法是:建立一个POS[i]数组,记录i进入dp[LEN]的时候,是在什么长度[也就是LEN]进入的。

比如现在有

st字符串:

st[0]st[1]st[2]st[3]
adfc

dp数组:

再次强调,dp[x]数组里面的自变量x是LIS子串的长度。

dp[1]dp[2]dp[3]
ad

f

c想要进入,因该进入长度为2的dp[2]中,也就是长度为2的子序列的末尾可以更小,所以

pos[3]=2。

最后的dp数组:

dp[1]dp[2]dp[3]dp[4]
acf 

最后的pos数组:

pos[0]pos[1]pos[2]pos[3]
1232

然后我们来还原原来的LIS的样子。

最长的是pos[2]也就是末尾是s[2]('c')的LIS是最长的,它是从谁的身上接上去的呢?

有两个pos的值是2,也就是3,要想变成3,一定是从2的身上接上去的。

考虑pos[3],st[2]是接在st[3]的身上吗?显然不可能,这是因为,st[3]在st[2]之后,怎么样都不可能拼接在一起。

那么pos[1]也是2,所以st[2]是从st[1]拼接起来的。

同理st[1]也是由st[0]拼接的。

那么有人问,

pos[...]pos[i-2]pos[i-1]pos[i]
...223

st[i]是从谁拼接的呢。

从pos[i-1]还是从pos[i-2]呢。

首先搞明白为什么pos[i-2]==pos[i-1]这是因为在长度为2的子串的时候,s[i-1]能比s[i-2]字典序更小,然后也能满足dp[2]的LEN==2的要求,所以其实s[i] 既可以从s[i-1]拼接,也可以s[i-2]拼接,只不过是我们要求字典序最小,所以我们选择了pos[i-1](也就是最靠后的,pos的值是2的,那个位置)来拼接。

小熊想请您仔细阅读:

    int tmp = n;
    while (len>0) {
        if (pos[tmp] == len) {
            ans.push_back(s[tmp]);
            len--;
            tmp--;
        }
        else
            tmp--;
    }

这段代码,这段代码就是我上面所讲的这个思想。

然后下面是这道题目代码的全貌。 

#include<iostream>
#include<vector>

using namespace std;
const int N = 1e6 + 10;
string s[N]/*拆分出的字符串数组*/ , dp[N] /*递推数组*/, S/*原始字符串*/;
vector<string> ans;
int pos[N] /*记录位置*/, n = -1;

signed main() {
    ios::sync_with_stdio(false);
    cin >> S;
    /*===拆分字符串===*/
    string now = "";
    for (int i = 0; i < S.size(); i++) {
        if (S[i] >= 'A' && S[i] <= 'Z') {
            s[++n] = now;
            now = S[i];
        } else now += S[i];
    }
    /*===拆分字符串 end===*/

    int len = 1;
    s[++n] = now;
    dp[len] = s[1];// 递推数组,dp(i)表示以长度为i的lis的结尾元素
    pos[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (dp[len] < s[i]) { // i位置的元素比较大,那么lis长度会变化
            dp[++len] = s[i], pos[i] = len;  // 每次从s数组里加入到𝑑𝑝中时,可以记录下s[𝑖]的位置
        } else {
            int j = lower_bound(dp + 1, dp + 1 + len, s[i]) - dp; // 折半查找
            dp[j] = s[i]; // 更新
            pos[i] = j;
        }
    }
    int tmp = n;
    while (len>0) {
        if (pos[tmp] == len) {
            ans.push_back(s[tmp]);
            len--;
            tmp--;
        }
        else
            tmp--;
    }
//    ans.push_back(s[tmp]);
    for (int i = ans.size() - 1; i >= 0; i--) cout << ans[i];
    cout << '\n';
    return 0;
}

试题:

题目描述:

 

解析:

先把题目读懂,s+a时间一到,消息就发出去了。

对于这道题,其实如果想不出来正确的解法。小熊建议可以写一个全排列程序,然后做模拟找出时间总和最小的排列,先把一部分的分数拿到手再说。

如果要想知道正确的解法,就必须仔细思考。

假设:我们有1~n个同学需要去答疑。

第一个同学发消息的时刻是s_1+a_1

第二个同学发消息的时刻是s_1+a_1+e_1+s_2+a_2

第三个同学发消息的时刻是s_1+a_1+e_1+s_2+a_2+e_2+s_3+a_3

第四个同学发消息的时刻是s_1+a_1+e_1+s_2+a_2+e_2+s_3+a_3+e_3+s_4+a_4

....

第n个同学发消息的时刻是  s_1+a_1+e_1+s_2+a_2+...+e_{n-1}+s_n+a_n

 

所以总时刻是,把上面这些时刻全部加起来。

请观察上面的规律。

n*(s_1+a_1)+(n-1)*e_1 + (n-1)*(s_2+a_2) +(n-2)*e_2 + ....+ 1 *(s_n+a_n) + 0*e_n

也就是第n - i +1位同学(n是固定的,比如现在i=n,那就是第1位同学),对上一行这个式子的贡献是:(n - i +1)*(s_i+a_i) + (n - i)*(e_i)

或者说第i位同学的贡献值是:

(i)*(s_{n+1-i}+a_{n+1-i}) + (i-1)*(e_{n+1-i})

要求保证这个最终答案最小。我们s,a,e是天生的,改变的是乘以他们的因子。

n*(s_1+a_1)+(n-1)*e_1 + (n-1)*(s_2+a_2) +(n-2)*e_2 + ....+ 1 *(s_n+a_n) + 0*e_n

对于s1和a1,n是他们的因子。对于sn和an,1是他们的因子。

所以s1+a1尽量选择小一点的 sn和an尽量选择大一点的。

这就是贪心。

本题解答完毕,具体实现请看代码。

正解代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
struct node {
    int s, a, e;
    //重新定义排序的规则
    bool operator<(const node& x) const { return (s + a + e) < (x.s + x.a + x.e); }
};
vector<node> vec;
signed main() {
    int n, ans = 0;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        int s, a, e;
        cin >> s >> a >> e;
        vec.push_back(node{s, a, e});
    }
    sort(vec.begin(), vec.end());
    for (int i = 0; i < n; i++) {
        int s = vec[i].s, a = vec[i].a, e = vec[i].e;
        ans += (n - i) * (s + a) + (n - i - 1) * e;
    }
    cout << ans << '\n';
    return 0;
}

宇宙第一小正太\(^o^)/~爆表求带=≡Σ((( つ^o^)つ~ dalao们点个关注呗~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值