【解题报告】活跃思想训练4(上) | CF 数论2000+ | 前六题

  • 补题场,把提交数高的一些漏的数论的2000+的题都收集进来了。

A:SUM and REPLACE | CF 920F

题意

  1. R E P L A C E   l ,   r REPLACE\ l,\ r REPLACE l, r,对于每一个 i ∈ [ l , r ] i\in[l,r] i[l,r],让 a i = D ( a i ) a_i=D(a_i) ai=D(ai),其中 D ( x ) D(x) D(x) 表示 x x x 的因子个数
  2. S U M   l   r SUM\ l\ r SUM l r,求出 ∑ i = l r a i \sum_{i=l}^r a_i i=lrai
  • 1 ≤ n , m ≤ 3 ⋅ 1 0 5 1\le n,m\le 3\cdot 10^5 1n,m3105
    1 ≤ a i ≤ 1 0 6 1\le a_i\le 10^6 1ai106

思路

  • 简单题。每个数操作不多就可以变为 1 1 1 或者 2 2 2,然后就不变了。
    多写一个标记,记一下是否覆盖的区间都是不会变了。

代码

  • 时间复杂度: O ( n log ⁡ n ) O(n\log n) O(nlogn)
#include<bits/stdc++.h>
using namespace std;
void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}
#define ls (p<<1)
#define rs (p<<1|1)
#define md ((l+r)>>1)
#define ll long long
const int MAX = 1e6+50;
ll aa[MAX];
ll tree[MAX*4];
bool fin[MAX*4];

int mp[MAX];
int tau[MAX];

int cnt;
bool vis[MAX];
int pri[MAX];

void shai(int n){
    tau[1] = 1;mp[1] = 0;
    for(int i = 2;i <= n;++i){
        if(!vis[i]){
            pri[++cnt] = i;
            tau[i] = 2;mp[i] = 1;
        }
        for(int j = 1;j <= cnt && i * pri[j] <= n;++j){
            vis[i * pri[j]] = 1;
            if(i % pri[j]){
                tau[i * pri[j]] = tau[i] * 2;
                mp[i * pri[j]] = 1;
            }else{
                tau[i * pri[j]] = tau[i] / (mp[i] + 1) * (mp[i] + 2);
                mp[i * pri[j]] = mp[i] + 1;
                break;
            }
        }
    }
}

inline void push_up(int p){
    tree[p]=tree[ls]+tree[rs];
    fin[p] = fin[ls] & fin[rs];
}
inline void build(int p,int l,int r){
    fin[p] = 0;
    if(l == r){
        tree[p] = aa[l];
        if(tree[p] == tau[tree[p]])fin[p] = 1;
        return;
    }
    build(ls,l,md);
    build(rs,md+1,r);
    push_up(p);
}
inline void update(int p,int l,int r,int ux,int uy){
    if(fin[p])return;
    if(l == r){
        tree[p] = tau[tree[p]];
        if(tree[p] == tau[tree[p]])fin[p] = 1;
        return;
    }
    if(ux <= md)update(ls,l,md,ux,uy);
    if(uy >  md)update(rs,md+1,r,ux,uy);
    push_up(p);
}
inline ll query(int p,int l,int r,int qx,int qy){
    ll res = 0;
    if(qx <= l && r <= qy)return tree[p];
    if(qx <= md)res += query(ls,l,md,qx,qy);
    if(qy >  md)res += query(rs,md+1,r,qx,qy);
    return res;
}
int main()
{
    shai(1000000);
    int n,m;scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;++i)scanf("%d",&aa[i]);
    build(1,1,n);

    for(int i = 1;i <= m;++i){
        ll op,t1,t2;
        scanf("%lld",&op);
        if(op == 1){
            scanf("%lld%lld",&t1,&t2);
            update(1,1,n,t1,t2);
        }else{
            scanf("%lld%lld",&t1,&t2);
            printf("%lld\n",query(1,1,n,t1,t2));
        }
    }
    return 0;
}

B:Roman and Numbers | CF 401D

题意

  • Roman and Numbers | CF 401D
    给定一个数 x x x,把它的各个数位全排列后得到一个新的没有前导零的数字 y y y
    满足 y ∣ m y|m ym,求这样不同的 y y y 的个数
  • 1 ≤ n < 1 0 18 1\le n< 10^{18} 1n<1018
    1 ≤ m ≤ 100 1\le m\le 100 1m100

思路

  • 求全排列,不能爆搜,那我们可以用状压,来记录我们目前已经选了哪些数字。
    然后,考虑最后整除 m m m,我们多记录一个状态,表示目前选完组成的数字取模 m m m 是多少。
    就是记 d p [ S ] [ j ] dp[S][j] dp[S][j] 表示已选数字集合为 S S S,且这个数字的排列的值取模 m m m j j j 的方案数。
  • 然后我们每一次新选择一个新的数字,往下简单递推即可。最终答案就是 d p [ a l l ] [ 0 ] dp[all][0] dp[all][0]

代码

  • 时间复杂度: O ( 2 18 × 18 × 100 ) O(2^{18}\times 18 \times 100) O(218×18×100)
#include<bits/stdc++.h>
using namespace std;
void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}
typedef long long ll;
const int MAX = 1e5+50;
const int MOD = 1e9+7;

int cnt;
int arr[20];
int num[20];
ll dp[1<<18][105];

ll getFac(int x){
    ll res = 1;
    for(ll i = 2;i <= x;++i)res *= i;
    return res;
}

int main()
{
    ll n;int m;cin >> n >> m;
    while(n){
        arr[cnt++] = n % 10;
        num[n %10]++;
        n /= 10;
    }
    int ed = 1<<cnt;
    dp[0][0] = 1;

    for(int i = 0;i < ed;++i){
        for(int j = 0;j < m;++j){
            if(!dp[i][j])continue;
            for(int k = 0;k < cnt;++k){
                if(i>>k&1)continue;
                if(i == 0 && arr[k] == 0)continue;
                dp[i|(1<<k)][(j*10+arr[k])%m] += dp[i][j];
            }
        }
    }

//    show(dp[ed-1][0]);

    for(int i = 0;i < 10;++i)dp[ed-1][0] /= getFac(num[i]);

    cout << dp[ed-1][0];


    return 0;
}

C:Cut | CF 1516D

题意

  • Cut | CF 1516D
    给你长度为 n n n 的序列 a n a_n an,给你 m m m 个询问
    每次询问,给你一个 l , r l,r l,r,问你这一段 a l ∼ a r a_l\sim a_r alar 最少分成几个连续的子段,满足每个子段的 l c m lcm lcm 等于这个子段中每个元素的乘积?
  • 1 ≤ n , q , a i ≤ 1 0 5 1\le n,q,a_i\le 10^5 1n,q,ai105

思路

  • 好 题 \color{blue}{好题}
    如果只是一次询问,怎么做?
    首先题意的这个子段必须满足区间内元素两两不互素。
    每一次从最左边 x x x 开始,贪心取,取到最大的 y y y,满足 ( a x , a x + 1 , ⋯   , a y ) (a_x,a_x+1,\cdots,a_y) (ax,ax+1,,ay) 内的元素都两两不互素。然后开始下一个区间。
  • 这里有许多分支的思考。我们一个一个提出,一个一个解决。
    (1)这个贪心有什么启发?
    考虑到我们每一个元素 a i a_i ai 作为子段的左顶点的话,这个子段的最右顶点的下标我们记作 n x t [ i ] nxt[i] nxt[i]
    由于左顶点不断向右移动,不互素条件越来越容易,所以我们的右顶点的下标是单调不降的
    也就是我们可以使用类似双指针的方式去得到所有的 n x t [ i ] nxt[i] nxt[i]
    (2) 如何判断子段内的元素两两不互素来得到我们的 n x t [ i ] nxt[i] nxt[i]
    我们如果获得了每个元素 a i a_i ai 的所有质因子集合 A \mathbb{A} A,我们对于每一个质因子开一个 v i s [ p ] vis[p] vis[p] 表示这个子段内是否已经有这个质因子了。如果我新加进来的数字的某个 p p p 满足加进来之前已经 v i s [ p ] = 1 vis[p]=1 vis[p]=1 了,那当然不满足互素条件了。新加进来数字和删除数字对 v i s [ p ] vis[p] vis[p] 的影响都很好写。
    注意,一个数字的因子个数是 O ( n 1 / 3 ) O(n^{1/3}) O(n1/3) 级别的。但是我们不要直接 O ( n 3 / 2 ) O(n^{3/2}) O(n3/2) 去获得所有的因子,我们可以先枚举因子再枚举数,这样可以复杂度变成 O ( n log ⁡ n ) O(n\log n) O(nlogn)
    (3)有了 n x t [ i ] nxt[i] nxt[i] 数组了,我们怎么求一次询问的答案?
    每一次我都跳 n x t [ i ] nxt[i] nxt[i],直到 n x t [ i ] ≥ r nxt[i]\ge r nxt[i]r了,那么跳的次数当然就是这个区间内最少数量的子段了。
    (4)但是多次询问,不是很优啊?怎么优化呢?
    考虑我们每一次跳一次 n x t [ i ] nxt[i] nxt[i],确实挺劣的。我们可以使用倍增表,一次跳多个,这样跳的次数就可以控制在 log ⁡ \log log 次了。注意,我们需要改一下 n x t [ i ] nxt[i] nxt[i] 数组的定义,改成最右的右顶点的下一个位置。这样,就可以直接使用倍增表了。
    倍增表 n x t [ i ] [ j ] nxt[i][j] nxt[i][j] 表示从 i i i 开始,跳 2 j 2^j 2j 步,右区间的下一个位置在哪里。如果它 ≤ r \le r r,就表示我们要跳。当然这里的 j j j 是从大往小枚举的。

代码

  • 时间复杂度: O ( ( n + q ) log ⁡ n ) O((n+q)\log n) O((n+q)logn)
#include<bits/stdc++.h>
using namespace std;
void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}
typedef long long ll;
const int MAX = 1e5+50;
const int MOD = 1e9+7;

int cnt;
bool vis[MAX];
int pri[MAX];

vector<int>fac[MAX];

int aa[MAX];
int nxt[MAX][30];

int vis2[MAX];

void shai(int x){
    for(int i = 2;i <= x;++i){
        if(!vis[i])pri[++cnt]=i;
        for(int j = 1;j <= cnt && i * pri[j] <= x;++j){
            vis[i * pri[j]] = 1;
            if(i % pri[j] == 0)break;
        }
    }

    for(int i = 1;i <= cnt;++i)
    for(int j = 1;j * pri[i] <= x;++j){
        fac[pri[i] * j].push_back(i);
    }
}

void change(int x,int k){
    int val = aa[x];
    for(auto it : fac[val])vis2[it] += k;
}


bool check(int nxtPos){
    int val = aa[nxtPos];
    for(auto it : fac[val])if(vis2[it])return false;
    return true;
}

int main()
{
    shai(100000);
    int n,q;
    scanf("%d%d",&n,&q);
    for(int i = 1;i <= n;++i){
        scanf("%d",&aa[i]);
    }
    int nxtPos=0;
    for(int i = 1;i <= n;++i){
        while(nxtPos+1 <= n && check(nxtPos+1)){
            change(nxtPos+1,1);
            nxtPos++;
        }
        change(i,-1);
        nxt[i][0] = nxtPos+1;
//        show(i,nxtPos);
    }

    for(int j = 0;j <= 20;++j)
        nxt[n+1][j] = n+1;

    for(int j = 1;j <= 20;++j)
    for(int i = 1;i <= n;++i)
        nxt[i][j] = nxt[nxt[i][j-1]][j-1];

    while(q--){
        int l,r;scanf("%d%d",&l,&r);
        int cnt = 0;
        int now = l;
        for(int i = 20;~i;--i){
            if(nxt[now][i] <= r){
                cnt += (1<<i);
                now = nxt[now][i];
            }
        }
        printf("%d\n",cnt+1);
    }

    return 0;
}

D:Recovering BST | CF 1025D

题意

  • Recovering BST | CF 1025D
    给定一棵树的中序遍历顺序 a n a_n an
    求问你能否构建出一颗这样的 B S T BST BST 树,且满足相连的两个节点的 gcd ⁡ > 1 \gcd >1 gcd>1
  • 2 ≤ n ≤ 700 2\le n\le 700 2n700
    2 ≤ a i ≤ 1 0 9 2\le a_i\le 10^9 2ai109

思路

  • 上来我们肯定会去想能否定义 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k] 表示区间 [ i , j ] [i,j] [i,j] 搭建一棵 B S T BST BST ,其中根为 k k k
    然后考虑转移。我们枚举 i , j , k i,j,k i,j,k,只要左边找一个根,右边找一个根,满足 d p [ i ] [ k − 1 ] [ r 1 ] = d p [ k + 1 ] [ r ] [ r 2 ] = 1 dp[i][k-1][r1]=dp[k+1][r][r2]=1 dp[i][k1][r1]=dp[k+1][r][r2]=1,然后要求两个根和 a k a_k ak gcd ⁡ > 1 \gcd >1 gcd>1,就可以转移过来了。
    但是这样子做的时间复杂度为 O ( n 4 ) O(n^4) O(n4),超时了。
  • 然后我去瞎搞贪心构造,但是很明显是不大行的,还是得去做 d p dp dp。我们得考虑优化。
    上面的问题就在于转移太复杂了,状态也很复杂,虽然看起来都是必须的。
    注意到一些必要的性质。如果我们能搭建起一棵 [ l , r ] [l,r] [l,r] 的树,不管这棵树的根是多少,它的父亲要么是 a l − 1 a_{l-1} al1,要么是 a r + 1 a_{r+1} ar+1,要么它没有父亲了。
  • 所以,我们定义状态 d p [ i ] [ j ] [ 0 / 1 ] dp[i][j][0/1] dp[i][j][0/1] 表示是否能搭建起一棵 [ i , j ] [i,j] [i,j] 的树,且根的父亲为 a i a_{i} ai (或者根的父亲为 a r a_{r} ar)。注意这里的范围!
    考虑转移。 d p [ i ′ ] [ j ′ ] [ 0 / 1 ] = d p [ i ] [ k ] [ 1 ] & d p [ k ] [ j ] [ 0 ] dp[i^\prime][j^\prime][0/1]=dp[i][k][1]\&dp[k][j][0] dp[i][j][0/1]=dp[i][k][1]&dp[k][j][0],且 gcd ⁡ ( k , f a ) > 1 \gcd(k,fa)>1 gcd(k,fa)>1
    很明显,我们把根为 k k k,拉出来,左子树可以满足向右的父亲为 k k k,右子树可以满足向左的父亲为 k k k
    然后再看是 0 / 1 0/1 0/1 决定 f a fa fa i − 1 i-1 i1 还是 j + 1 j+1 j+1,然后转移。
    最后如果存在 d p [ 1 ] [ n ] [ 0 / 1 ] = 1 dp[1][n][0/1]=1 dp[1][n][0/1]=1 那就是可以重构的,否则不行
  • 注意我们可以提前预处理 g g [ i ] [ j ] = gcd ⁡ ( a i , a j ) gg[i][j]=\gcd(a_i,a_j) gg[i][j]=gcd(ai,aj),否则又要多一个 log ⁡ \log log

代码

  • 时间复杂度: O ( n 3 ) O(n^3) O(n3),但是有很多冗余,所以不会跑满。
#include<bits/stdc++.h>
using namespace std;
void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}
typedef long long ll;
const int MAX = 1e5+50;
const int MOD = 1e9+7;

int aa[705];
int gg[705][705];
bool dp[705][705][2];

int main()
{
    int n;cin >> n;
    for(int i = 1;i <= n;++i)cin >> aa[i],dp[i][i][0] = dp[i][i][1] = 1;

    for(int i = 0;i <= n + 1;++i)
    for(int j = 0;j <= n + 1;++j)
        gg[i][j] = __gcd(aa[i],aa[j]);


    for(int Len = 1;Len <= n;++Len)
    for(int L = 1;L + Len - 1 <= n;++L){
        int R = L + Len - 1;
//        show(L,R,dp[L][R][0],dp[L][R][1]);
        for(int k = L;k <= R;++k){
            if(dp[L][k][1] && dp[k][R][0]){
                if(gg[L-1][k] > 1)dp[L-1][R][0] = 1;
                if(gg[R+1][k] > 1)dp[L][R+1][1] = 1;
                if(L == 1 && R == n){
                    puts("Yes");
                    return 0;
                }
            }
        }
    }
    puts("No");
    return 0;
}
/**
4
23 247 299 703
*/

E:Array and Operations | CF 498C

题意

  • Array and Operations | CF 498C
    给定一个序列 a n a_n an
    给定 m m m 对边 ( i m , j m ) (i_m,j_m) (im,jm),其中满足 i k + j k i_k+j_k ik+jk 是奇数,且 i k < j k i_k<j_k ik<jk
    你每次可以选择一对边 ( x , y ) (x,y) (x,y),然后选择一个 v v v,满足 v > 1 v>1 v>1 v ∣ a x v|a_{x} vax v ∣ a y v|a_y vay
    然后你就成功一次操作,然后让 a x = a x / v a_x=a_x/v ax=ax/v a y = a y / v a_y=a_y/v ay=ay/v
    问你最多进行多少次操作
  • 2 ≤ n ≤ 100 2\le n\le 100 2n100
    1 ≤ m ≤ 100 1\le m\le 100 1m100
    1 ≤ a i ≤ 1 0 9 1\le a_i\le 10^9 1ai109

思路

  • 数和边非常的少。我们直接考虑拿出每一个质因子,然后对于所有的边,我们把这两个元素中相同的质因子连边,容量为正无穷
    因为每个质因子只能被算一次,我们拆点,入点连出点,容量为 1 1 1
    最后跑一个最大流就可以了。

代码

  • 时间复杂度: O ( 可 以 过 ) O(可以过) O()
#include<bits/stdc++.h>
using namespace std;
void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}
typedef long long ll;
const int MAX = 1e6+50;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

struct edge{
    int to;
    ll cap;
    int rev;
};
vector<edge>G[MAX];
int level[MAX];     /// 深度数组
int iter[MAX];      /// 当前弧优化

void add_edge(int from,int to,ll cap){
    G[from].push_back({to,cap,G[to].size()});
    G[to].push_back({from,0,G[from].size()-1});
}
void bfs(int s){
    memset(level,-1,sizeof(level));
    level[s] = 0;
    queue<int>Q;
    Q.push(s);
    while(!Q.empty()){
        int v = Q.front();Q.pop();
        for(auto it : G[v]){
            if(it.cap > 0 && level[it.to] < 0){
                level[it.to] = level[v] + 1;
                Q.push(it.to);
            }
        }
    }
}
ll dfs(int v,int t,ll f){
    if(v == t)return f;
    for(int &i = iter[v];i < G[v].size();++i){
        edge &e = G[v][i];
        if(e.cap > 0 && level[v] < level[e.to]){
            ll d = dfs(e.to,t,min(f,e.cap));
            if(d > 0){
                e.cap -= d;
                G[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}
ll max_flow(int s,int t){
    ll flow = 0;
    while(1){
        bfs(s);
        if(level[t] < 0)return flow;
        memset(iter,0,sizeof(iter));
        ll f = -1;
        while(f){
            f = dfs(s,t,LINF);
            flow += f;
        }
    }
}

int aa[MAX];

vector<pair<int,int> >V[MAX];

int main()
{
    int n,m;cin >> n >> m;
    for(int i = 1;i <= n;++i)cin >> aa[i];

    int cnt = 0;
    for(int i = 1;i <= n;++i){
        int tmp = aa[i];
        for(int j = 2;j * j <= tmp;++j){
            if(tmp % j == 0){
                while(tmp % j == 0){
                    tmp /= j;
                    V[i].push_back(make_pair(++cnt,j));
                }
            }
        }
        if(tmp > 1)V[i].push_back(make_pair(++cnt,tmp));
    }

    int S = 0,T = 2 * cnt + 1;

    for(int i = 1;i <= n;++i){
        for(auto it : V[i]){
            int x = it.first;
            add_edge(x,x+cnt,1);
            if(i&1)add_edge(S,x,INF);
            else add_edge(x+cnt,T,INF);
        }
    }

    while(m--){
        int ta,tb;
        cin >> ta >> tb;
        for(auto it : V[ta])
        for(auto it2: V[tb]){
            if(it.second == it2.second){
                if(ta&1)add_edge(it.first+cnt,it2.first,INF);
                else add_edge(it2.first+cnt,it.first,INF);
            }
        }
    }

    cout << max_flow(S,T);
    return 0;
}
/**

*/

F:Send Boxes to Alice (Hard Version) | CF 1254B2

题意

  • Send Boxes to Alice (Hard Version) | CF 1254B2
    给定一个序列 a n a_n an
    每一次移动,你可以选择两个相邻的元素(也就是 a b s ( p 1 − p 2 ) = 1 abs(p1-p2)=1 abs(p1p2)=1),然后把其中一个位置的元素 + 1 +1 +1,另一个位置的元素 − 1 -1 1
    问你最少的移动次数,满足这个序列的 gcd ⁡ > 1 \gcd>1 gcd>1
    如果做不到,输出 − 1 -1 1
    数据满足至少存在一个正整数 a i a_i ai
  • 1 ≤ n ≤ 1 0 6 1\le n\le 10^6 1n106
    0 ≤ a i ≤ 1 0 6 0\le a_i\le 10^6 0ai106

思路

  • 好 题 \color{blue}{好题}
    看到这种题,想到对于每一个 gcd ⁡ = k \gcd=k gcd=k,我都去 c h e c k check check 一下,算一下移动次数的最少值。
    但是每一次操作,让一个加一另一个减一的操作非常不好搞。
    然后我们换一种思路。我们记前缀和 S i = a 1 + a 2 + ⋯ + a i S_i=a_1+a_2+\cdots+a_i Si=a1+a2++ai
    容易得到,我们要让 k ∣ S i k|S_i kSi,且我们每一次的移动操作只会让一个 S i S_i Si 加一或者减一。
    这就非常好做了。
  • 对于每一个特定的 k k k S i S_i Si 要减或者加的操作来满足是 k k k 的倍数,也就是我们取 min ⁡ { S i % k , k − S i % k } \min\{S_i\%k,k-S_i\%k\} min{Si%k,kSi%k}
  • 但是对于每一个 k k k 我们都求一遍还是不大行呀。这个时候我们想到,我们的 k k k 只取合理的质数即可。因为在上述 % k \%k %k 的前提下,且段是成倍数的情况下,段长度越小,灵活性越大。

代码

  • 时间复杂度: O ( n × log ⁡ n ) O(n \times \log n) O(n×logn)
#include<bits/stdc++.h>
using namespace std;
void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}
typedef long long ll;
const int MAX = 1e6+50;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

int aa[MAX];
ll pre[MAX];


ll check(ll x,int n){
    ll ans = 0;
    for(int i = 1;i <= n;++i){
        ans += min(pre[i]%x,x-(pre[i]%x));
    }
//    show(x,ans);
    return ans;
}

int main()
{
    ll sum = 0;
    int n;scanf("%d",&n);
    for(int i = 1;i <= n;++i)scanf("%d",&aa[i]),sum += aa[i],pre[i] = pre[i-1] + aa[i];

    ll ans = LINF;

    for(ll i = 2;i * i <= sum;++i){
        if(sum % i == 0){
            ans = min(ans,check(i,n));
            while(sum % i == 0)sum /= i;
        }
    }
    if(sum > 1)ans = min(ans,check(sum,n));

    if(ans == LINF)puts("-1");
    else printf("%lld",ans);

    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值