【基于连通性的状态压缩DP】【NOI2007】生成树计数

n个结点的无向完全图的生成树的个数 头部闲扯 今天闲来在google搜了一下cantjie,突然发现我的博客竟然被引用过,很是惊讶。因为虽然仅仅只是过去一年,我现在看我去年写的博客,就有种“这写的什么垃圾玩意”的感觉,没想到竟然也会有人浏览并引用我的博客。 想来这个博客闲置一年多了,突然就想再拾起来看看,能不能再偶尔写几篇,不一定为了分享给谁看,也是为了给自己整理一下思路。 正文 刚到新加坡,前两天介绍了一下 commu... 阅读详情
问题描述
最近,小栋在无向连通图的生成树个数计算方面有了惊人的进展,他发现:
·n 个结点的环的生成树个数为 n。
·n 个结点的完全图的生成树个数为 n^(n-2)。
这两个发现让小栋欣喜若狂,由此更加坚定了他继续计算生成树个数的想法,他要计算出各种各样图的生成树数目。
一天,小栋和同学聚会,大家围坐在一张大圆桌周围。小栋看了看,马上想到了生成树问题。如果把每个同学看成一个结点,邻座(结点间距离为 1)的同学间连一条边,就变成了一个环。可是,小栋对环的计数已经十分娴熟且不再感兴趣。于是,小栋又把图变了一下:不仅把邻座的同学之间连一条边,还把相隔一个座位(结点间距离为 2)的同学之间也连一条边,将结点间有边直接相连的这两种情况统称为有边相连,如图 1 所示。

小栋以前没有计算过这类图的生成树个数,但是,他想起了老师讲过的计算任意图的生成树个数的一种通用方法:构造一个 n×n 的矩阵 A={aij}

其中 di 表示结点 i 的度数。
与图 1 相应的 A 矩阵如下所示。为了计算图 1 所对应的生成数的个数,只要去掉矩阵 A 的最后一行和最后一列,得到一个(n-1)×(n-1)的矩阵 B,计算出矩阵B 的行列式的值便可得到图 1 的生成树的个数。

所以生成树的个数为 B = 3528 。小栋发现利用通用方法,因计算过于复杂而很难算出来,而且用其他方法也难以找到更简便的公式进行计算。于是,他将图做了简化,从一个地方将圆桌断开,这样所有的同学形成了一条链,连接距离为 1 和距离为 2 的点。例如八个点的情形如下:

这样生成树的总数就减少了很多。小栋不停的思考,一直到聚会结束,终于找到了一种快捷的方法计算出这个图的生成树个数。可是,如果把距离为 3 的点也连起来,小栋就不知道如何快捷计算了。现在,请你帮助小栋计算这类图的生成树的数目。
输入文件
输入文件中包含两个整数 k, n,由一个空格分隔。k 表示要将所有距离不超过 k(含 k)的结点连接起来,n 表示有 n 个结点。
输出文件
输出文件输出一个整数,表示生成树的个数。由于答案可能比较大,所以你只要输出答案除 65521 的余数即可。
输入样例
35
输出样例
75
样例说明
样例对应的图如下:




朴素模拟代码:

/***************************\
 * @prob: NOI2007 count    *
 * @auth: Wang Junji       *
 * @stat: TLE: 40          *
 * @date: May. 29th, 2012  *
 * @memo: 模拟              *
\***************************/
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <cstring>

const int maxN = 1010, MOD = 65521;
typedef long long int64;
long long a[maxN][maxN], ans;
int ord[maxN], n, K;

int main()
{
    freopen("count.in", "r", stdin);
    freopen("count.out", "w", stdout);
    scanf("%d%d", &K, &n);
    for (int i = 1; i < n; ++i)
    for (int j = 1; j < n; ++j)
    if (i == j) a[i][j] = std::min(n, i + K) - std::max(1, i - K);
    else a[i][j] = (abs(i - j) <= K) ? -1 : 0;
    for (int i = 1; i < n; ++i) ord[i] = i;
    ans = 1;
    for (int i = 1; i < n; ++i) (ans *= a[i][i]) %= MOD;
    for (;;)
    {
        std::next_permutation(ord + 1, ord + n);
        if (ord[1] > K + 1) break;
        bool br = 1, cn = 0;
        for (int i = 1; i < n; ++i)
        if (ord[i] > i + K || ord[i] < i - K)
            {cn = 1; break;}
        if (cn) continue;
        for (int i = 1; i < n; ++i)
            if (ord[i] - i) {br = 0; break;}
        if (br) break;
        long long tmp = 1;
        for (int i = 1; i < n; ++i)
            if (!((tmp *= a[i][ord[i]]) %= MOD)) break;
        do
        {
            if (!tmp) break;
            for (int i = 1; i < n; ++i)
            for (int j = i + 1; j < n; ++j)
                if (ord[i] > ord[j]) tmp = -tmp;
        } while (0);
        (ans += tmp) %= MOD;
    }
    printf("%d\n", (int)((ans + MOD) % MOD));
    return 0;
}
但此题正解并不是用行列式来进行计算,而是基于连通性的状态压缩DP。
用f[i][j]表示前i个结点中,倒数K个结点的连通性为j的方案总数(其中用最小表示法来描述倒数K个结点的连通性)。
首先用一个递归来找出所有的状态。(如K = 3时有111,112,121,122,123五种状态;K = 4时有15种状态;K = 5时有52种状态。)
程序中为了方便,一律使用八进制倒序存储每一个状态。

我们在每一种状态中,要维护出该状态对应的实际情况有多少种,可以用题目中给出的行列式算出。(比如状态111对应3种不同的生成树;状态1111对应16种不同的生成树;状态11111对应125种不同的生成树。)

那么在递推的时候,要保证以下两点:
 1) 由当前状态推出的下一状态不能有环;
 2) 由当前状态推出的下一状态必须与当前状态所有的点都连通。
而我们可以用并查集来判断并求出所有满足条件的转移数,存储在g数组中, 方便转移。

于是转移的方程为:
最后只需要输出f[n][0](即所有点都连通,由于状态111或1111或11111总是第一个生成出来,序号为1)。
代码:

/******************************\
 * @prob: NOI2007 count       *
 * @auth: Wang Junji          *
 * @stat: RE: 80              *
 * @date: May. 30th, 2012     *
 * @memo: 基于连通性的状压DP     *
\******************************/
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>

typedef long long int64;
const int maxN = 10010, maxS = 60, MOD = 65521;
int64 f[maxN][maxS], n;
int status[maxS], ord[060000], g[maxS][maxS], F[10], K, cnt_s;

inline bool check(int ths)
{
    int tmp = 2;
    for (int i = 3; i < K * 3; i += 3)
    {
        for (int j = 1; j < ((ths >> i) & 7); ++j)
            if (!(tmp & (1 << j))) return 0;
        tmp |= 1 << ((ths >> i) & 7);
    } //用最小表示法的定义来判断状态ths是否合法。
    return 1;
}

void Find(int x, int ths)
{
    if (x >= K)
    {
        if (check(ths)) ord[ths] = cnt_s, status[cnt_s++] = ths;
        return;
    }
    for (int i = 1; i < K + 1; ++i) Find(x + 1, ths | (i << (3 * x)));
    return;
} //递归生成每一种状态。

static int Find(int x) {return F[x] == x ? x : (F[x] = Find(F[x]));}

int main()
{
    freopen("count.in", "r", stdin);
    freopen("count.out", "w", stdout);
    scanf("%d%lld", &K, &n);
    Find(1, 1);
    for (int i = 0; i < cnt_s; ++i)
    {
        f[K][i] = 1;
        static int cnt[10];
        memset(cnt, 0, sizeof cnt);
        for (int j = 0; j < K; ++j) ++cnt[(status[i] >> (j * 3)) & 7];
        for (int j = 1; j < K + 1; ++j)
        {
            if (cnt[j] == 3) f[K][i] = 3;
            if (cnt[j] == 4) f[K][i] = 16;
            if (cnt[j] == 5) f[K][i] = 125;
        }
        int ths = status[i];
        for (int s = 0; s < (1 << K); ++s)
        //01枚举下一个点与当前状态中所有点的连通关系。
        {
            for (int j = 0; j < K + 1; ++j) F[j] = j; //并查集数组初始化。
            for (int j = 0; j < K; ++j)
            for (int k = j + 1; k < K; ++k)
            if (((ths >> (j * 3)) & 7) == ((ths >> (k * 3)) & 7))
                F[Find(j)] = Find(k);
            //将当前状态中的连通关系维护出来。
            bool flag = 1;
            for (int j = 0; j < K; ++j) if (s & (1 << j))
            {
                if (Find(K) - Find(j)) F[F[j]] = F[K];
                else {flag = 0; break;}
            }
            //将下一个点与当前状态中相连的点的连通关系维护出来并排除环。
            if (!flag) continue; flag = 0;
            for (int j = 1; j < K + 1; ++j)
                if (Find(0) == Find(j)) {flag = 1; break;}
            //保证当前状态的第一个点与后面的至少一个点相连,
            //否则整个图将会从此处断开。
            if (!flag) continue;
            int use = 0, nxt = 0;
            for (int j = 0; j < K; ++j)
            if (!(nxt & (7 << (j * 3))))
            {
                nxt |= ++use << (j * 3);
                for (int k = j + 1; k < K; ++k)
                if (Find(j + 1) == Find(k + 1))
                    nxt |= use << (k * 3);
            } //根据最小表示法的规则生成下一个状态。
            ++g[i][ord[nxt]];
            //由于多种不同的连通性可能对应同一种状态,
            //所以要把所有的情况都算进来。
        }
    }
    //找出每个状态能够推出那些状态,并求出转移数
    //(即从i~K+i-1的连通性推出i+1~K+i)
    for (int i = K + 1; i < n + 1; ++i)
    for (int j = 0; j < cnt_s; ++j)
    for (int k = 0; k < cnt_s; ++k)
        if (g[j][k]) (f[i][k] += g[j][k] * f[i - 1][j]) %= MOD;
    printf("%d\n", (int)f[n][0]);
    return 0;
}
直接递推的效率太低!
当我们发现所有转移都是相同的的时候,就应该想到——矩阵!矩阵乘法可以帮助我们快速转移!

就把之前用来转移的g数组转置(交换行列坐标)过后作为基底,将基底自乘n - K次之后在乘以在K处的所有状态即得到了最终的所有状态。
代码:

/********************************************\
 * @prob: NOI2007 count                     *
 * @auth: Wang Junji                        *
 * @stat: Accepted.                         *
 * @date: May. 30th, 2012                   *
 * @memo: 基于连通性的状压DP、矩阵乘法优化       *
\********************************************/
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>

typedef long long int64;
const int maxN = 10010, maxS = 60, MOD = 65521;
int64 vect[maxS], res, n;
int status[maxS], ord[060000], F[10], K, cnt_s;

struct Matrix
{
    int64 a[maxS][maxS];
    Matrix() {memset(a, 0, sizeof a);}
    Matrix &operator=(const Matrix &b)
    {memcpy(a, b.a, sizeof b.a); return *this;}
    Matrix &operator*=(const Matrix &b)
    {
        Matrix ans;
        for (int i = 0; i < cnt_s; ++i)
        for (int j = 0; j < cnt_s; ++j)
        for (int k = 0; k < cnt_s; ++k)
            (ans.a[i][j] += a[i][k] * b.a[k][j]) %= MOD;
        memcpy(a, ans.a, sizeof ans.a);
        return *this;
    }
} g;

inline bool check(int ths)
{
    int tmp = 2;
    for (int i = 3; i < K * 3; i += 3)
    {
        for (int j = 1; j < ((ths >> i) & 7); ++j)
            if (!(tmp & (1 << j))) return 0;
        tmp |= 1 << ((ths >> i) & 7);
    }
    return 1;
}

void Find(int x, int ths)
{
    if (x >= K)
    {
        if (check(ths)) ord[ths] = cnt_s, status[cnt_s++] = ths;
        return;
    }
    for (int i = 1; i < K + 1; ++i) Find(x + 1, ths | (i << (3 * x)));
    return;
}

static int Find(int x) {return F[x] == x ? x : (F[x] = Find(F[x]));}

inline void pow(Matrix &a, int64 n)
{
    Matrix ans;
    for (int i = 0; i < cnt_s; ++i) ans.a[i][i] = 1;
    for (; n; n >>= 1, a *= a) if (n & 1) ans *= a;
    a = ans; return;
}

int main()
{
    freopen("count.in", "r", stdin);
    freopen("count.out", "w", stdout);
    scanf("%d%lld", &K, &n);
    Find(1, 1);
    for (int i = 0; i < cnt_s; ++i)
    {
        vect[i] = 1; static int cnt[10];
        memset(cnt, 0, sizeof cnt);
        for (int j = 0; j < K; ++j) ++cnt[(status[i] >> (j * 3)) & 7];
        for (int j = 1; j < K + 1; ++j)
        {
            if (cnt[j] == 3) vect[i] = 3;
            if (cnt[j] == 4) vect[i] = 16;
            if (cnt[j] == 5) vect[i] = 125;
        }
        int ths = status[i];
        for (int s = 0; s < (1 << K); ++s)
        {
            for (int j = 0; j < K + 1; ++j) F[j] = j;
            for (int j = 0; j < K; ++j)
            for (int k = j + 1; k < K; ++k)
            if (((ths >> (j * 3)) & 7) == ((ths >> (k * 3)) & 7))
                F[Find(j)] = Find(k);
            bool flag = 1;
            for (int j = 0; j < K; ++j) if (s & (1 << j))
            {
                if (Find(K) - Find(j)) F[F[j]] = F[K];
                else {flag = 0; break;}
            }
            if (!flag) continue; flag = 0;
            for (int j = 1; j < K + 1; ++j)
                if (Find(0) == Find(j)) {flag = 1; break;}
            if (!flag) continue;
            int use = 0, nxt = 0;
            for (int j = 0; j < K; ++j) if (!(nxt & (7 << (j * 3))))
            {
                nxt |= ++use << (j * 3);
                for (int k = j + 1; k < K; ++k)
                if (Find(j + 1) == Find(k + 1))
                    nxt |= use << (k * 3);
            }
            ++g.a[ord[nxt]][i];
        }
    }
    pow(g, n - K);
    for (int i = 0; i < cnt_s; ++i)
        (res += g.a[0][i] * vect[i]) %= MOD;
    printf("%d\n", (int)res);
    return 0;
}

[NOI2007]生成树计数 (基于连通性的状态压缩动态规划+矩阵快速幂优化) 题意:n个点排成一排,每个点往它前k个点连边,求生成树个数。 n&amp;lt;=1e15,k&amp;lt;=5n&amp;lt;=1e15,k&amp;lt;=5n&lt;=1e15,k&lt;=5 其实这个题很OI的。 考虑从左到右把点加入然后维护生成树个数,可以发现需要区分的状态只有前k的点的联通情况(快速判断成环或不连通),然后最小表示法基于连通性的状态压缩dp一发,然后就是喜闻乐见的发... 阅读详情

相关推荐

离散数学——通俗易懂的描述:无向树&生成树

T为连通图G的一个生成树,C是G中任意圈==>T的余树的边肯定参与成C的边。(2)T为无向连通图G的一个生成树==>T的余树的边数为(m-n+1)(6)G无圈,若在任意两顶点之间加一条新边,就是G中唯一的一个圈。(理解:有n-1条边用来当生成树了,剩下的就是余树的边~)(注意啦:余树虽然名字里面有树,但不一定是树!tn表:n无向树对应的树,给定n,查表得到tn。(1)G为无向连通图==>(m>=n-1)(1)G是树(没有回路,连通)生成树T:G的生成子图,且为树。树枝:既在G中,也在T中的边。

m0_74028782的博客 4419

无向连通图生成树个数

对于一个无向连通图来说,它可能有很多生成树,那么如何求得它的生成树个数呢?首先给出一个非常一般的计算方法 -- 矩阵行列式法对于任何一个顶点数为n的无向连通图,我们列出一个矩阵。矩阵的规则是:1、在主对角线上的元素为此节点的度数2、对于其他位置上的元素Matrix(i,j) { i != j },   (1) 如果节点i和节点j连通,则Matrix(i,j)的值为-k,其中k值为节点i到节

gqjjqg的专栏 6213

Mongodb操作与Java(四)MongoTemplate的使用

MongoTemplate的使用

A乐神的博客 3417

最小生成树,克鲁斯卡尔(Kruskal)算法, 普里姆(Prim)算法

最小生成树,克鲁斯卡尔(Kruskal)算法, 普里姆(Prim)算法

m0_75027890的博客 628

【数据结】图的定义、存储

一个有n个顶点和n条边的无向图一定是有环的一个无向图有n个顶点和n-1条边,可以使它连通单没有环,若再加一条边,则会形成环若图中顶点数为n,则它的生成树有n-1条边,去掉一条边变成非连通图;加上一条边变成一个回路(环)2.(D)对于n个顶点,e条边的无向图,所有顶点的度之和为2e,即无向图的全部顶点的度的和等于边数的两倍【分析】设顶点有x个,则20+12+2(x-9)=46,x=163.在n个顶点的有向图中,顶点的度最大可达2n-2【分析】有向图中,顶点的度=出度+入度。

m0_51403396的博客 1229

BZOJ 1494 NOI2007 生成树计数 状压DP+矩阵乘法

题目大意:给定n(n≤1015)n(n\leq 10^{15})个点,编号差不超过k(k≤5)k(k\leq 5)的点之间有连边,问生成树个数 将kk个点的连通性用最小表示法压成状态,那么最多有5252种状态 计算出每个状态的生成树个数,作为初始行向量AA 对于每种状态考虑新加入一个点并向这kk个点连边,每种连法可以转移到哪些状态,得到转移矩阵BB 那么答案就是A∗Bn[A*B^n[所有点都

世界 2446

bzoj1494: [NOI2007]生成树计数

传送门 将k个点的连通性用最小表示法压成状态,那么最多有52种状态 最小表示法中,f[i]表示最小的与其联通的点编号。 计算出每个状态的生成树个数,作为初始行向量A 对于每种状态考虑新加入一个点并向这k个点连边,每种连法可以转移到哪些状态,得到转移矩阵B 那么答案就是A∗Bn[所有点都连通的状态] 就是代码炒鸡长。#include<cmath> #include<cstdio> #inc

zyy大蒟蒻的博客 707

[NOI2007]生成树计数

题意 一个nnn个点的树,点iii只能向[i−k,i−1][i−k,i−1][i-k,i-1]内的点连边,求有标号生成树的个数 n≤1015,k≤5n≤1015,k≤5n\le10^{15},k\le5 题解 题面误导向系列,显然不能像他说的那样做吧 因为发现kkk特别小,所以可以考虑用状压表示iii和前k−1k−1k-1个点的联通情况 考虑DP,f[i][j]DP,f[i][j]...

BeNoble_的博客 615

【BZOJ1494】生成树计数NOI2007)-连通性状压DP+矩阵加速

测试地址:生成树计数 做法:本题需要用到连通性状压DP+矩阵加速。 假设图是从左到右不断添加点的,那么每添加一个点,影响到的只有最后kkk个点的连通性,所以不难想到以最后kkk个点的连通性作为状态进行DP。所谓的连通性,就是将这kkk个点分为若干个集合,相同集合内的点就是连通的,不同集合内的点就不连通,不难发现合法的状态数只有B(k)B(k)B(k),即第kkk个Bell数,而Bell数就是k...

Maxwei_wzj的OI世界 379

[BZOJ1494][NOI2007]生成树计数(状压dp+矩阵乘法)

Address https://www.lydsy.com/JudgeOnline/problem.php?id=1494 Solution 定义状态: f[i][S]f[i][S]f[i][S] 表示 iii 个点的图,编号差 ≤k≤k\le k 的点对之间有连边,现选出一些边,连通第 111 个点到第 i−ki−ki-k 个点,第 i−k+1i−k+1i-k+1 个点到第 iii ...

女装的你,如此好看! 416

NOI2008 生成树计数

<br /> <br />2011/2/8<br />生成树计数<br /> <br />题目我就不放了。 <br /> <br />栋栋十分xe的把大家往行列式上面引,但是是不能用行列式做的。观察这道题的特点,k特别小,因此这肯定是切入点。所以用状态f[I,j]表示前i个,联通状态为j(为长度为k的最小表示)的方案数。依次处理从左到右的点,往状态右边加入一个点,并往左边的点连边,删去原来最左边的点。可行的连边是使得原来最左边的元素的联通块有延续,注意这个时候要对状态重新最小表示法,重新标号,因为关心的只是

fly-fly 1046

[BZOJ 1494][NOI 2007]生成树计数(状压DP+最小表示法+矩阵乘法)

题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=1494思路由于每个点ii只能和点i−Ki-K到i−1i-1连边,因此点i−K+1i-K+1和其前面的所有点一定是都在同一个联通块。因此我们只需要用一个长度为KK的序列来表示点i−K+1i-K+1到点ii的连通性,而其他的点一定是连通的,就不必表示连通性了。这个连通性的序列可以用最小表示法压缩成一

某沙茶的OI代码库 2303

NOI知识点

NOI知识点

unknown 1512

【学习笔记】简单的连通性状压DP——插头DP(不学以为是天书)

不学不会,一学还是不会。

5578

[NOI2007]生成树计数(状压dp+矩阵加速)

【题解】 考虑动态规划的状态转移: 从左往右,加入第n个结点时,只考虑它向前连的边,那么答案就与向前连哪些边,以及之前的n-1个点成的答案有关  然而,"向前连哪些边"并不是有2^k种情况  前n个点成了许多连通块,而非一树  因此,结点n引出的边既要使结点1~n连通,也不能成环  而n只能向 n-k ~ n-1 连边  所以n的答案只与结点n-k~n-1的连通性有关 

cjk_My steps 753

无相连通图的生成树个数

通过看大神博客,总结了两种做法:解法一:基尔霍夫矩阵(暴力解法 O(n^3) 适用于n       http://www.4ucode.com/Study/Topic/1940063对于一个无向连通图,我们可以根据以下规则列出一个矩阵M:①主对角线上的值M(i,i)为i节点的度。②a[i,j]的值为点i到点j的平行边的条数的相反数,对于简单图a[i,j] = -1。显然,如果i,j不连通,M(i,

HjKon的专栏 2880

n无向简单图的不同个数——Burnside定理及代码实现

算法 计算nnn元对称群SnS_nSn​的,即为∣Sn∣=n!|S_n|=n!∣Sn​∣=n! 进行和式分解,如 4=1+1+1+1=2+1+1=2+2=3+1 \begin{aligned} 4&=1+1+1+1\\ &=2+1+1\\ &=2+2\\ &=3+1 \end{aligned} 4​=1+1+1+1=2+1+1=2+2=3+1​ 计算每...

thinszx的博客 4108

图论学习笔记(三) 树

前言:参考教材:《集合论与图论》第三版 屈婉玲,刘捍贫,刘田 第九章 树 9.1 无向树的定义及性质 无向树:连通且无回路(简单/初级)的无向图称为无向树,记为T;若无向图G中至少有两个连通分支且每个连通分支都是树,则称F为森林,平凡图称为平凡树 树叶/分支点:T=<V,E>为一颗无向树,若d(v)=1,则称为一个树叶;若d(v)≥2,则称为一个分支点。(如果n≥2,则树中的顶点要么是树叶,要么是分支点;但是n=1的时候平凡图中仅有的一个顶点既不是树叶也不是分支点) Theorem:G为nm边

ldc1513的博客 6552

MATLAB基础应用精讲-【图像处理】GNN图神经网络(附python代码实现)

图神经网络由于其在处理非欧空间数据和复杂特征方面的优势,受到广泛关注并应用于推荐系统、知识图谱、交通道路分析等场景。图结可描述复杂关系,如基因结、通信网络、交通路线、社交网络等。图计算挖掘结信息,但无法学习节点特征。神经网络在欧氏空间数据上表现优越,但无法直接应用于非欧氏空间的图数据。图神经网络结合图计算和神经网络优势,处理非欧氏空间数据及其复杂特征,应用于网络链接预测、推荐系统和交通道路分析等场景。实际应用中,图数据规模庞大,如百亿级节点、千亿级边,存储开销超过10TB。

qq_36130719的博客 1096

海康威视PuTTY+tftpd64+TTL串口刷机工具 (c)

海康威视录像机升级过程中断电导致升级失败可使用本工具刷机抢救!前提需要自备串口连接线!

上一篇: 【基于贪心的树型动态规划】【NOI2007】追捕盗贼
下一篇: 【树状数组】树状数组复习
Whjpji
博客等级 码龄15年 55粉丝 181原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值