CCF-CSP 第23次认证考试 202109-3脉冲神经网络(模拟)(100分)

问题描述

试题编号:202109-3
试题名称:脉冲神经网络
时间限制:1.0s
内存限制:512.0MB
问题描述:

题目背景

在本题中,你需要实现一个 SNN(spiking neural network,脉冲神经网络)的模拟器。一个 SNN 由以下几部分组成:

  1. 神经元:按照一定的公式更新内部状态,接受脉冲并可以发放脉冲
  2. 脉冲源:在特定的时间发放脉冲
  3. 突触:连接神经元-神经元或者脉冲源-神经元,负责传递脉冲

题目描述

神经元会按照一定的规则更新自己的内部状态。本题中,我们对时间进行离散化处理,即设置一个时间间隔 Δt,仅考虑时间间隔整数倍的时刻 t=kΔt(k∈Z+),按照下面的公式,从 k−1 时刻的取值计算 k 时刻的变量的取值:

vk=vk−1+Δt(0.04vk−12+5vk−1+140−uk−1)+Ik

uk=uk−1+Δta(bvk−1−uk−1)

其中 v 和 u 是神经元内部的变量,会随着时间而变化,a 和 b 是常量,不会随着时间变化;其中 Ik 表示该神经元在 k 时刻接受到的所有脉冲输入的强度之和,如果没有接受到脉冲,那么 Ik=0。当进行上面的计算后,如果满足 vk≥30,神经元会发放一个脉冲,脉冲经过突触传播到其他神经元;同时,vk 设为 c 并且 uk 设为 uk+d,其中 c 和 d 也是常量。图 1 展示了一个神经元 v 变量随时间变化的曲线。

 
图1: 神经元 v 变量随时间变化的曲线

突触表示的是神经元-神经元、脉冲源-神经元的连接关系,包含一个入结点和一个出结点(可能出现自环和重边)。当突触的入结点(神经元或者脉冲源)在 k 时刻发放一个脉冲,那么在传播延迟 D(D>0) 个时刻以后,也就是在 k+D 时刻突触的出结点(神经元)会接受到一个强度为 w 的脉冲。

脉冲源在每个时刻以一定的概率发放一个脉冲,为了模拟这个过程,每个脉冲源有一个参数 0<r≤32,767,并统一采用以下的伪随机函数:

C++ 版本:

static unsigned long next = 1;

/* RAND_MAX assumed to be 32767 */
int myrand(void) {
    next = next * 1103515245 + 12345;
    return((unsigned)(next/65536) % 32768);
}

C++

Python 版本:

next = 1
def myrand():
    global next
    next = (next * 1103515245 + 12345) % (2 ** 64)
    return (next // 65536) % 32768

Python

Java 版本:

long next = 1;
int myrand() {
    next = next * 1103515245 + 12345;
    return (int)((Long.divideUnsigned(next, 65536)) % 32768);
}

Java

在每个时间刻,按照编号顺序从小到大,每个脉冲源调用一次上述的伪随机函数,当 r>myrand() 时,在当前时间刻发放一次脉冲,并通过突触传播到神经元。

进行仿真的时候,已知 0 时间刻各个神经元的状态,从 1 时间刻开始按照上述规则进行计算,直到完成 T 时刻的计算,再输出 T 时刻神经元的 v 值和发放的脉冲次数分别的最小值和最大值。

规定输入数据中结点按如下方式顺序编号:[0,N−1] 为神经元的编号,[N,N+P−1] 为脉冲源的编号。

代码中请使用双精度浮点类型。

输入格式

从标准输入读入数据。

输入的第一行包括四个以空格分隔的正整数 N S P T,表示一共有 N 个神经元,S 个突触和 P 个脉冲源,输出时间刻 T 时神经元的 v 值。

输入的第二行是一个正实数 Δt,表示时间间隔。

输入接下来的若干行,每行有以空格分隔的一个正整数 RN 和六个实数 v u a b c d,按顺序每一行对应 RN 个具有相同初始状态和常量的神经元:其中 v u 表示神经元在时刻 0 时的变量取值;a b c d 为该神经元微分方程里的四个常量。保证所有的 RN加起来等于 N。它们从前向后按编号顺序描述神经元,每行对应一段连续编号的神经元的信息。

输入接下来的 P 行,每行是一个正整数 r,按顺序每一行对应一个脉冲源的 r 参数。

输入接下来的 S 行,每行有以空格分隔的两个整数 s(0≤s<N+P)、t(0≤t<N) 、一个实数 w(w≥0) 和一个正整数 D,其中 s 和 t 分别是入结点和出结点的编号;w 和 D 分别表示脉冲强度和传播延迟。

输出格式

输出到标准输出。

输出共有两行,第一行由两个近似保留 3 位小数的实数组成,分别是所有神经元在时刻 T 时变量 v 的取值的最小值和最大值。第二行由两个整数组成,分别是所有神经元在整个模拟过程中发放脉冲次数的最小值和最大值。

只要按照题目要求正确实现就能通过,不会因为计算精度的问题而得到错误答案。

样例1输入

1 1 1 10
0.1
1 -70.0 -14.0 0.02 0.2 -65.0 2.0
30000
1 0 30.0 2

Data

样例1输出

-35.608 -35.608
2 2

Data

样例1解释

该样例有 1 个神经元、1 个突触和 1 个脉冲源,时间间隔 Δt=0.1。唯一的脉冲源通过脉冲强度为 30.0、传播延迟为 2 的突触传播到唯一的神经元。

该样例一共进行 10 个时间步的模拟,随机数生成器生成 10 次随机数如下:

16838
5758
10113
17515
31051
5627
23010
7419
16212
4086

None

因此唯一的脉冲源在时刻 1-4 和 6-10 发放脉冲。在时间刻从 1 到 10 时,唯一的神经元的 v 取值分别为:

-70.000
-70.000
-40.000
-8.200
-65.000
-35.404
-32.895
0.181
-65.000
-35.608

None

该神经元在时刻 5 和时刻 9 发放,最终得到的 v=−35.608 。

样例2输入

2 4 2 10
0.1
1 -70.0 -14.0 0.02 0.2 -65.0 2.0
1 -69.0 -13.0 0.04 0.1 -60.0 1.0
30000
20000
2 0 15.0 1
3 1 20.0 1
1 0 10.0 2
0 1 40.0 3

Data

样例2输出

-60.000 -22.092
1 2

Data

子任务

子任务TNSPD分值
1≤102≤102≤102≤102≤10230
2≤103≤103≤103≤103≤10340
3≤105≤103≤103≤103≤1030

/*
*@Author:   GuoJinlong
*@Language: C++
*/
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<list>
#include<set>
#include<iomanip>
#include<cstring>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cassert>
#include<sstream>
#include<algorithm>
using namespace std;
typedef long long  ll;
#define ull unsigned long long
#define scf(n) scanf("%d",&n)
#define scfl(n) scanf("%lld",&n)
#define prf(n) printf("%d",n)
#define prfl(n) printf("%lld",n)
#define scfd(n) scanf("%lf",&n)
#define prfd(n) printf("%.lf",n)
#define prf10(n) printf("%.10f",n)
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r)/2
#define mms(x, y) memset(x, y, sizeof x)
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
const int INF = 0x3f3f3f3f;
const double EPS=1e-10;
const double Pi=3.1415926535897;
inline double max(double a,double b){
    return a>b?a:b;
}
inline double min(double a,double b){
    return a<b?a:b;
}
inline int read() {
    int x=0,f=1; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    return x*f;
}
int xd[8] = {0, 1, 0, -1, 1, 1, -1, -1};
int yd[8] = {1, 0, -1, 0, -1, 1, -1, 1};
 
//fastPow
int fastPow(int x,int n){
    if(n==1) return x;
    int tmp=fastPow(x,n/2); //fenzi
    if(n%2==1) return tmp*tmp*x;
    else return tmp*tmp;
}
ll gcd(ll m, ll n){return n == 0 ? m : gcd(n, m%n);}
ll lcm(ll m, ll n){return m*n / gcd(m, n);}
ll pows(ll base, ll power,ll mod){ll result=1;while(power>0){if(power&1){result=result*base%mod;}power>>=1;base=(base*base)%mod;}return result;}
 
ll poww(ll base, ll power){ll result=1;while(power>0){if(power&1){result=result*base;}power>>=1;base=(base*base);}return result;}


//dijsktra
//start
//const int MAX= 10020;
//struct node {
//    int x,to,next,w;
//    bool operator <(const node &a) const{
//        return this->w>a.w;
//    }
//}G[MAX<<1];
//int cnt;
//int dis[MAX];
//int vis[MAX];
//int head[MAX];
//
//
//int m,n;
//int b[10020];
//
//
//void add(int u,int v,int w){
//    G[++cnt].to=v;
//    G[cnt].w=w;
//    G[cnt].next=head[u];
//    head[u]=cnt;
//}
//int  dijkstra(int s){
//    mms(dis,INF);
//    dis[s]=0;
//    priority_queue<node> p;
//    node t;
//    t.x=s;
//    t.w=0;
//    p.push(t);
//    while (!p.empty()) {
//        node u=p.top();
//        p.pop();
//        int v=u.x;
//        if(dis[v]!=u.w) continue;
//        for(int i=head[v];i;i=G[i].next){
//            int to=G[i].to;
//            if(dis[to]>dis[v]+G[i].w){
//                dis[to]=dis[v]+G[i].w;
//                t.x=to;
//                t.w=dis[to];
//                p.push(t);
//            }
//
//        }
//    }
//    int m1=-1;
//        int m2=-1;
//        dis[s]=-3;
//        for(int i=1;i<=n;i++){
//            if(dis[i]==INF) continue;
//            if(dis[i]>m1){
//                m2=m1;
//                m1=dis[i];
//            }
//            else if(dis[i]>m2){
//                m2=dis[i];
//            }
//        }
//        if(m1!=-1&&m2!=-1) return m1+m2;
//        return -1;
//
//}
//
//
//int main(){
//    int t;
//    cin>>t;
//    while (t--) {
//        cin>>n>>m;
//        int u,v,w;
//
//        for(int i=1;i<=m;i++){
//            cin>>u>>v>>w;
//            add(u,v,w);
//            add(v,u,w);
//        }
//        int ans=0;
//        int cnt=0;
//        for(int i=1;i<=n;i++){
//            ans=max(ans,dijkstra(i));
//        }
//        cout<<ans<<endl;
//    }
//}
//end


//e_cheak
//int vis[1000010];
//int prime[100010];
//int  e_cheak(int n){   //k为2-n素数的个数
//    for(int i=0;i<=n;i++){
//        vis[i]=0;
//    }
//    for(int i=2;i*i<=n;i++){
//        if(!vis[i]){
//            for(int j=i*i;j<=n;j+=i){
//                vis[j]=1;
//            }
//        }
//    }
//    int k=0;
//    for(int i=2;i<=n;i++){
//        if(!vis[i])
//            prime[k++]=i; //统计素数
//    }
//    return k;
//}
//
进制转化 x转化为y进制
//string work(int x,int y){
//    string str="";
//    while(x){
//        if(x%y>=10) str+=x%y+'A'-10;
//        else str+=x%y+'0';
//        x/=y;
//    }
//    reverse(str.begin(),str.end());
//    return str;
//}
//
//
//const int MAX=1000005;
//char str[MAX];
//char pattern[MAX];
//int cnt;
//int Next[MAX];
//void  getnext(string p,int plen){
//    Next[0]=0;
//    Next[1]=0;
//    for(int i=1;i<plen;i++){
//        int j=Next[i];
//        while (j&&p[i]!=p[j]) {
//            j=Next[j];
//        }
//        Next[i+1]=(p[i]==p[j])?j+1:0;
//    }
//}
//int kmp(string s,string p){
//    int last=-1;
//    int slen=s.length();
//    int plen=p.length();
//    getnext(p,plen);
//    int j=0;
//    for(int i=0;i<slen;i++){
//        while (j&&s[i]!=p[j]) {
//            j=Next[j];
//        }
//        if(s[i]==p[j]) j++;
//        if(j==plen){
//            //start
//            return 1;
//            //end
//        }
//    }
//    return 0;
//}
//int main(){
//    int n;
//    cin>>n;
//    string t;
//    string s="";
//    for(int i=2;i<=16;i++){
//        s="";
//        s+=work(n,i);
//        if(kmp(s,t))
//        {
//            cout<<"yes";
//            return 0;
//        }
//    }
//    cout<<"no"<<endl;
//    return 0;
//}


//string s1,s2;
//int main(){
//    cin>>s1;
//    s2="cocacola";
//    int ans;
//    for(int i=0;i<s1.length();i++){
//        if(s1[i]!=s2[i])
//            ans++;
//    }
//    cout<<ceil(ans/2);
//}


//const int MAX=10010;
//
//int n;
//int a[MAX];
//int st[MAX],ed[MAX];
//int pos[MAX];
//int sum[MAX];
//int add[MAX];
区间修改
//void change(int l,int r,int d){
//    int p=pos[l];
//    int q=pos[r];
//    if(p==q){ //情况1 区间位于一个块里面
//        for(int i=l;i<=r;i++){
//            a[i]+=d;
//        }
//        sum[p]+=d*(r-l+1);
//    }
//    else { //区间跨多个块
//        for(int i=p+1;i<=q-1;i++){
//            add[i]+=d; //完整的块里面的数据直接加上d
//        }
//        for(int i=l;i<=ed[p];i++){ //整块前面的散块
//            a[i]+=d;
//        }
//        sum[p]+=d*(ed[p]-l+1);
//        for(int i=st[q];i<=r;i++){ //整块后面的散块
//            a[i]+=d;
//        }
//        sum[q]+=d*(r-st[q]+1);
//    }
//}
//
//ll query(int l,int r){
//    int p=pos[l];
//    int q=pos[r];
//    ll ans=0;
//    if(p==q){ //整块
//        for(int i=l;i<=r;i++){
//            ans+=a[i];
//        }
//        ans+=add[p]*(r-l+1);
//    }
//    else { //有散块
//        for(int i=p+1;i<=q-1;i++){
//            ans+=sum[i]+add[i]*(ed[i]-st[i]+1); //先处理整块
//        }
//        for(int i=l;i<=ed[p];i++){ //整合散块
//            ans+=a[i];
//        }
//        ans+=add[p]*(ed[p]-l+1);
//        for(int i=st[q];i<=r;i++){
//            ans+=a[i];
//        }
//        ans+=add[q]*(r-st[q]+1);
//    }
//    return ans;
//}
//
//int main(){
//
//
//    cin>>n;
//    for(int i=1;i<=n;i++){
//        cin>>a[i];
//    }
//    //start
//    int block=sqrt(n);
//    int t=n/block;
//    if(n%block) t++;
//    for(int i=1;i<=t;i++){
//        st[i]=(i-1)*block+1;
//        ed[i]=i*block;
//    }
//    ed[t]=n;
//    for(int i=1;i<=n;i++){
//        pos[i]=(i-1)/block+1; //pos是第i个元素所在的块
//    }
//
//
//    for(int i=1;i<=t;i++){
//        for(int j=st[i];j<=ed[i];j++){
//            sum[i]+=a[j];  //sum是第i块的区间和
//        }
//    }
//    //end
//
//    int opt,l,r,c;
//    for(int i=1;i<=n;i++){
//        cin>>opt>>l>>r>>c;
//        if(opt==1){
//            cout<<query(r,r)<<endl;
//        }
//        else {
//            change(l,r,c);
//        }
//    }
//}
//


const int MAX=1e3+5;
int N,S,P,T;
double dt;
double u,v,a,b,c,d;
int rn,rns;
int maxd;
double maxv=-INF,minv=INF;
int maxtime=-INF,mintime=INF;
int r[MAX];
vector<int>G[MAX<<1]; //用vector容器存放节点连接情况
struct ce{
    double u,v,a,b,c,d;
    int time; //神经元发射脉冲的次数
}ces[MAX];
struct mc{
    int s,t;
    double w;
    int D;
}mcs[MAX];


//
static unsigned long next1 = 1;

/* RAND_MAX assumed to be 32767 */
int myrand(void) {
    next1 = next1 * 1103515245 + 12345;
    return((unsigned)(next1/65536) % 32768);
}
//


int main(){
    rns=0;
    cin>>N>>S>>P>>T;
    cin>>dt;
    while (rns<N) {
        cin>>rn>>v>>u>>a>>b>>c>>d;
//        over(i,rns,rns+rn-1)
        //更新的是每段时间的神经元信息
        for(int i=rns;i<rns+rn;i++)
        {
            ces[i].v=v;
            ces[i].u=u;
            ces[i].a=a;
            ces[i].b=b;
            ces[i].c=c;
            ces[i].d=d;
            ces[i].time=0;
        }
        rns+=rn; //为了满足rn之和=rns
    }
//    over(i,0,P-1)
    for(int i=0;i<P;i++)
        cin>>r[i];
//    over(i,0,S-1)
    for(int i=0;i<S;i++)
    {
        cin>>mcs[i].s>>mcs[i].t>>mcs[i].w>>mcs[i].D;
        maxd=max(maxd,mcs[i].D);
        G[mcs[i].s].push_back(i);//存放节点连接情况
    }
    int mod=maxd+1;
    vector<vector<double>> I(mod,vector<double>(N));
//    over(k,0,T-1)
    for(int k=0;k<T;k++)
    {
        //Ik表示每时刻受到的脉冲之和 所以每次都要清零
//        over(i,0,N-1)
        for(int i=0;i<N;i++)
            I[(k+maxd)%mod][i]=0;
        
        
        //脉冲过程的模拟
//        over(i,0,P-1)
        for(int i=0;i<P;i++)
        {
            int my=myrand();
            if(r[i]>my){
//                over(j,0,G[N+i].size()-1)
                for(int j=0;j<G[N+i].size();j++) //传向连接的所有神经元
                {
                    mc m=mcs[G[N+i][j]];
                    I[(k+m.D)%mod][m.t]+=m.w;
                }
            }
        }
        
        //
//        over(i,0,N-1)
        for(int i=0;i<N;i++)
        {
            double v1=ces[i].v;
            double u1=ces[i].u;
            double a1=ces[i].a;
            double b1=ces[i].b;
            ces[i].v=v1+dt*(0.04*v1*v1+5*v1+140-u1)+I[k%mod][i];
            ces[i].u=u1+dt*a1*(b1*v1-u1);
            if(ces[i].v>=30){
                ces[i].time++;
                for(int j=0;j<G[i].size();j++)
//                over(j,0,G[i].size()-1)
                {
                    mc m=mcs[G[i][j]];
                    I[(k+m.D)%mod][m.t]+=m.w;
                }
                ces[i].v=ces[i].c;
                ces[i].u+=ces[i].d;
            }
        }
        
    }
//    over(i,0,N-1)
    for(int i=0;i<N;i++)
    {
        maxv=max(maxv,ces[i].v);
        minv=min(minv,ces[i].v);
        maxtime=max(maxtime,ces[i].time);
        mintime=min(mintime,ces[i].time);
    }
    cout<<fixed<<setprecision(3)<<minv<<" "<<maxv<<endl;
    cout<<mintime<<" "<<maxtime<<endl;
    return 0;
}

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
### 回答1: CCF-CSP(中国计算机学会认证系统程序员)认证考试是由中国计算机学会主办的,旨在选拔高水平的系统程序员和开发人员。该认证考试包括两个级别:初级和高级。初级考试主要测试候选人的基础知识和编程能力,高级考试则主要测试候选人的系统设计和开发能力。CCF-CSP认证考试的评标准严格,要求考生表现出扎实的计算机理论基础和熟练的编程技巧。 为了顺利通过CCF-CSP认证考试,考生需要掌握扎实的计算机基础知识和熟练的编程技巧,并且需要在考试前进行充的准备。以下是一些复习技巧指导: 1. 确认考试大纲 考生需要仔细阅读考试大纲,了解考试范围和题型。要特别注意考试大纲中的重点内容,重点复习。 2. 提前规划复习进度 准备CCF-CSP认证考试需要时间,而时间是很宝贵的,考生需要提前规划好复习进度和复习内容,尽可能利用零散时间进行复习。 3. 多做题 要想掌握CCF-CSP认证考试所需的知识和技能,考生需要多做题,并针对性地练习一些经典的考题。在练习中,考生需要注重练习思路和解题方法,该方法可以加深对知识点的理解。 4. 关注考试动态 考试动态指的是考试历年来的趋势和变化,考生需要不断关注考试动态,了解考试趋势,及时更新复习内容和方法,以便更好地应对考试。 总之,要想通过CCF-CSP认证考试,考生需要理论基础和开发经验充足,并且需要在复习时切实遵循学科规范,灵活应用知识点,较好地掌握考试技巧,这是顺利通过CCF-CSP认证考试的关键。 ### 回答2: ccf-csp认证考试是中国计算机学会(CCF认证的一个计算机软件专业技能等级考试,也是中国IT行业里非常重要的证书之一。该考试为初级、中级和高级三个等级,其中初级考试包含了基础的程序设计和算法等内容,中级考试中主要考察了软件工程、数据结构、算法设计和网络安全等领域的知识,而高级考试则更注重的是对软件工程和软件项目管理的理解和应用,以及对复杂系统的设计和实现方法的掌握。为了能够成功通过ccf-csp认证考试,首先需要在考前充准备,并且需要有一些好的复习技巧,这里向大家推荐以下几点: 1.学好基础知识。初级、中级和高级csp认证考试所涉及到的内容都是建立在一定的基础知识上的。由于考试的难度逐级递增,所以建议在准备考试之前先花时间学好基础知识。 2.多做练习题。做练习题能够帮助我们加深对知识的理解,熟悉考试形式和规则,同时也能提高我们的答题速度和准确度。 3.注意时间管理。不同级别的csp认证考试都有时限,在考试过程中需要注意时间的配。建议在每做练习题的时候都设置一个时间限制,并逐步缩短时间限制,以提高答题效率。 4.了解考试规则。在考前一定要熟悉考试规则和题型,知道考试时可以携带哪些资料和工具,了解考试的答题和评规则等。 总之,ccf-csp认证考试是一项非常重要的认证考试,通过这个认证不仅可以增加个人的职业竞争力,还能证明个人在软件开发和IT行业方面的专业能力。因此,我们需要认真地准备和复习,字斟句酌地做好每一个细节,以确保顺利通过考试。 ### 回答3: ccf-csp认证考试是由中国计算机学会主办的全国性计算机考试考试内容涵盖了计算机应用、技术、算法等多个方面,为初级、中级和高级三个等级。参加此考试不仅有助于检测个人的计算机专业水平,更能提升自身的竞争力和职业发展前景。 为了通过ccf-csp认证考试,考生需要重点复习考试要求中的各个内容模块,如数据类型、运算符、控制结构、数组、函数、文件操作等程序设计相关方面;还包括计算机网络、操作系统、数据库等计算机技术类知识;另外,还需要掌握常见算法和数据结构,如排序、查找、树等。此外,考生还需要通过大量的编程练习和模拟题练习,熟悉考试题型和答题技巧,提升自己的完成效率和准确性。 在复习过程中,需要注重细节和实践。例如,对于程序设计相关方面,需要理解每个知识点的原理和应用场景,在编写代码时要注重细节避免出现错误。对于算法和数据结构方面,需要熟悉常见算法的实现方式和优缺点,掌握好算法的时间复杂度和空间复杂度,做到熟练掌握。 总之,通过充准备和钻研,考生有望成功通过ccf-csp认证考试,展现自己的计算机专业能力和职业素养。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

郭晋龙

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

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

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

打赏作者

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

抵扣说明:

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

余额充值