C++模板

(考前复习)

一、图论

1、最小生成树

(1)Kruskal

 1 #include <algorithm>
 2 #include <cstdio>
 3 #define ll long long
 4 struct node{
 5     int u,v,w;
 6 }g[200005];
 7 int cnt,fa[100005],num,n,m;   
 8 void add(int x,int y,int z)
 9 {
10     g[++num].u=x;  g[num].v=y;  g[num].w=z;  
11     return;
12 }
13 bool cmp(node x,node y)
14 {
15     return x.w<y.w;
16 }
17 int find(int x)
18 {
19     if (x==fa[x]) return x;
20     return fa[x]=find(fa[x]);
21 }
22 ll Kruskal()
23 {
24     int i,cnt=0,fu,fv;
25     ll tot=0;//  最小生成树权值和
26     std::sort(g+1,g+m+1,cmp);
27     for (i=1;i<=n;i++) fa[i]=i;
28     for (i=1;i<=m;i++)
29     {
30         fu=find(g[i].u);
31         fv=find(g[i].v);
32         if (fu==fv) continue;
33         fa[fv]=fu;
34         tot+=g[i].w;
35         cnt++;
36         if (cnt==n-1) return tot;
37     }
38 }
39 int main()
40 {
41     int i,j,x,y,z;
42     scanf("%d%d",&n,&m);   //  n个 顶点,m 条边 
43     for (i=1;i<=m;i++)
44       scanf("%d%d%d",&x,&y,&z),
45       add(x,y,z);  //  x 和 y 有一条权值为 z 的边 
46     printf("%lld",Kruskal());
47     return 0;
48 }
View Code

 (2)Prim

1 #include <algorithm>
 2 #include <cstring>
 3 #include <cstdio>
 4 #define ll long long
 5 struct node{
 6     int u,w,nex;
 7 }g[200005];
 8 int num,n,m,fir[100005]; 
 9 bool vis[100005];
10 ll dis[100005];  
11 void add(int x,int y,int z)
12 {
13     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
14     return;
15 }
16 ll Prim()
17 {
18     int i,j,k,p,cnt=0;
19     ll tot=0,minv;  //  最小生成树权值和 
20     memset(dis,127,sizeof(dis));
21     dis[1]=0; 
22     while (cnt<n)
23     {
24         for (p=-1,minv=3e9,j=1;j<=n;j++)
25           if (!vis[j] && dis[j]<minv)
26             minv=dis[j],p=j;
27         tot+=dis[p];  vis[p]=1;  cnt++;
28         for (k=fir[p];k;k=g[k].nex)
29           if (!vis[g[k].u] && dis[g[k].u]>g[k].w) 
30             dis[g[k].u]=g[k].w;
31     } 
32     return tot;
33 }
34 int main()
35 {
36     int i,j,x,y,z;
37     scanf("%d%d",&n,&m);  // n 个顶点,m 条边 
38     for (i=1;i<=m;i++)
39       scanf("%d%d%d",&x,&y,&z),
40       add(x,y,z),add(y,x,z);  // x 和 y 之间有一条权值为 z 的边 
41     printf("%lld",Prim());
42     return 0;
43 }
View Code

 

2、最短路

(1)SPFA

 1 #include <algorithm>
 2 #include <cstring>
 3 #include <cstdio>
 4 #define ll long long
 5 const int maxn=10005;
 6 struct node{
 7     int u,w,nex;
 8 }g[500005];
 9 int num,n,m,fir[10005],s,q[10005],h,t; 
10 bool vis[10005];
11 ll dis[10005];  
12 void add(int x,int y,int z)
13 {
14     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
15     return;
16 }
17 void spfa()
18 {
19     int i,j,k,u,v;
20     for (i=1;i<=n;i++) dis[i]=2147483647;
21     dis[s]=0; h=0; t=1; q[1]=s; vis[s]=1;
22     while (h!=t)
23     {
24         (++h)%=maxn; u=q[h]; vis[u]=0;  
25         for (k=fir[u];k;k=g[k].nex)
26         {
27             v=g[k].u;
28             if (dis[u]+g[k].w<dis[v]) 
29             {
30                 dis[v]=dis[u]+g[k].w;
31                 if (!vis[v])
32                 {
33                     vis[v]=1;
34                     (++t)%=maxn;
35                     q[t]=v;
36                 }
37             }
38         }
39     }
40     return;
41 } 
42 int main()
43 {
44     int i,j,x,y,z;
45     scanf("%d%d%d",&n,&m,&s);  // n 个顶点,m 条边,起点 s 
46     for (i=1;i<=m;i++)
47       scanf("%d%d%d",&x,&y,&z),
48       add(x,y,z);  // 一条从 x 指向 y 的边权值为 z 
49     spfa();
50     for (i=1;i<=n;i++) printf("%d ",dis[i]);
51     return 0;
52 }
View Code

(2)SPFA双端队列优化

 1 #include <cstring>
 2 #include <cstdio>
 3 const int maxn=20005;
 4 struct node{
 5     int u,w,nex;
 6 }g[100005];
 7 int n,m,fir[10005],num,q[20005],dis[10005];
 8 bool vis[10005];
 9 void add(int x,int y,int z)
10 {
11     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
12     return;
13 }
14 void spfa(int S)
15 {
16     int u,v,i,h,t;
17     memset(dis,63,sizeof(dis));
18     memset(vis,0,sizeof(vis));
19     dis[S]=0;    
20     h=0;  t=1;  q[1]=S;  vis[S]=1;
21     while (h!=t)
22     {
23         (++h)%=maxn;
24         u=q[h];  vis[u]=0;
25         for (i=fir[u];i;i=g[i].nex)
26         {
27             v=g[i].u;
28             if (dis[v]>dis[u]+g[i].w)
29             {
30                 dis[v]=dis[u]+g[i].w;
31                 if (!vis[v])
32                 {
33                     vis[v]=1;
34                     if (dis[v]<dis[q[(h+1)%maxn]])
35                       q[h]=v,h=(h-1+maxn)%maxn;
36                     else (++t)%=maxn,q[t]=v;
37                 }
38             }
39         }
40     }
41     return;
42 }
43 int main()
44 {
45     int i,j,t,p,x,y,z;
46     scanf("%d%d",&n,&m);
47     for (i=1;i<=m;i++)
48       scanf("%d%d%d",&x,&y,&z),
49       add(x,y,z),add(y,x,z);
50     spfa(1);    
51     return 0;
52 }
View Code

(3)Dijkstra优先队列优化

1 #include <cstdio>
 2 #include <vector>
 3 #include <queue>
 4 #define ll long long
 5 #define pa pair<ll,int>
 6 using namespace std;
 7 struct node{
 8     int u,w,nex;
 9 }g[1000005];
10 int n,m,fir[500005],num;
11 ll dis[500005];
12 priority_queue <pa,vector<pa>,greater<pa> > q;
13 void add(int x,int y,int z)
14 {
15     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
16     return;
17 }
18 void dijkstra(int S)
19 {
20     int h=0,t=1,u,v,i;
21     for (i=1;i<=n;i++) dis[i]=1e15;
22     dis[S]=0;
23     q.push(make_pair(0,S));
24     while (!q.empty())
25     {
26         u=q.top().second;  q.pop();
27         for (i=fir[u];i;i=g[i].nex)
28         {
29             v=g[i].u;
30             if (dis[v]>dis[u]+g[i].w)
31               dis[v]=dis[u]+g[i].w,
32               q.push(make_pair(dis[v],v));     
33         }
34     }
35     return;
36 }
37 int main()
38 {
39     int i,j,x,y,z,p;
40     scanf("%d%d",&n,&m);
41     for (i=1;i<=m;i++)
42       scanf("%d%d%d",&x,&y,&z),
43       add(x,y,z),add(y,x,z);
44     dijkstra(1); 
45     return 0;
46 }
View Code

(4)Dijkstra手打堆优化

 1 #include <cstring>
 2 #include <cstdio>
 3 struct node{
 4     int u,w,nex;
 5 }g[400005];
 6 struct note{
 7     int dis,id;
 8 }h[100005];
 9 int n,m,fir[100005],d[100005],num;
10 int pos[100005],siz;
11 void add(int x,int y,int z) 
12 {
13     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
14     return;
15 }
16 void put(int x)
17 {
18     int fa;
19     note t;
20     while (x>1)
21     {
22         fa=x>>1;
23         if (h[x].dis>=h[fa].dis) break;
24         pos[h[x].id]=fa;  pos[h[fa].id]=x;
25         t=h[x];  h[x]=h[fa];  h[fa]=t;
26         x=fa;
27     }
28     return;
29 }
30 void get(int x)
31 {
32     int son;
33     note t;
34     h[1]=h[siz--];
35     while (x*2<=siz)
36     {
37         son=x<<1;
38         if (son<siz && h[son].dis>h[son+1].dis) son++;
39         if (h[x].dis<=h[son].dis) break;
40         pos[h[x].id]=son;  pos[h[son].id]=x;
41         t=h[x];  h[x]=h[son];  h[son]=t;
42         x=son;
43     }
44     return ;
45 }
46 void dijkstra()
47 {
48     int i,j,u,v,p;
49     note top;
50     for (i=1;i<=n;i++)
51       h[++siz].dis=d[i],h[siz].id=i,pos[i]=siz;
52     for (i=1;i<=n;i++)
53     {
54         top=h[1];  get(1);  pos[top.id]=0;
55         for (j=fir[top.id];j;j=g[j].nex)
56         {
57             v=g[j].u;
58             if (pos[v]>0 && top.dis+g[j].w<h[pos[v]].dis)
59               p=pos[v],
60               h[p].dis=top.dis+g[j].w,
61               d[v]=h[p].dis,
62               put(p);
63         }    
64     }  
65     return;
66 }
67 int main() 
68 {
69     int i,j,k,x,y,z;
70     memset(fir,0,sizeof(fir));
71     memset(d,63,sizeof(d));
72     scanf("%d%d",&n,&m);
73     d[1]=num=siz=0;
74     for (i=1;i<=m;i++)
75       scanf("%d%d%d",&x,&y,&z),
76       add(x,y,z);
77     dijkstra();
78     for (i=1;i<=n;i++)
79       printf("%d ",d[i]);
80     return 0;
81 }
View Code

(5)Floyd

 1 #include<cstdio>
 2 const int inf=1e9;
 3 int m,n; 
 4 int map[505][505],b[505],path[505][505];  //path[i][j]记录路径
 5 void floyd()
 6 {
 7     int i,j,k;
 8     for(k=1;k<=n;k++)
 9       for(i=1;i<=n;i++)
10         for(j=1;j<=n;j++)
11           if(map[i][j]>map[i][k]+map[k][j])
12             map[i][j]=map[i][k]+map[k][j], 
13             path[i][j]=path[i][k];
14     return;
15 }
16 int main()
17 {
18     int i,j,u,v,len;
19     scanf("%d%d",&n,&m); //输入城市数量 和 道路数量
20     //初始化
21     for(i=1;i<=n;i++)
22       for(j=1;j<=n;j++)
23         map[i][j]=inf,
24         path[i][j]=j;   
25     while(m--)
26       scanf("%d%d%d",&u,&v,&len),
27       map[u][v]=map[v][u]=len;
28     floyd();//进行每对节点的求最小路径
29     while(scanf("%d%d",&u,&v))
30     {//输入起点和终点
31         int tmp=u;
32         printf("%d",u);
33         while(tmp!=v)//打印路径
34           printf("-->%d",path[tmp][v]),
35           tmp=path[tmp][v];
36         //输出最小花费
37         printf("\n");
38         printf("cost: %d",map[u][v]);
39     }
40     return 0;
41 }
View Code

 

3、强连通分量

(1)Kosaraju

1 #include <cstdio>
 2 struct note{
 3     int u,nex;
 4 };
 5 note g[40005],gp[40005];
 6 int fir[205],firp[205],s,t,q[205],m,n;
 7 int mark[205];   // 点u属于哪个连通块 
 8 bool vis[205];
 9 void ADD(int k,int x,int y)
10 {
11     g[k].u=y;   g[k].nex=fir[x];   fir[x]=k;
12     gp[k].u=x;  gp[k].nex=firp[y]; firp[y]=k; 
13 }
14 void dfs1(int u)
15 {
16     vis[u]=true;
17     for (int k=fir[u];k;k=g[k].nex)
18       if (!vis[g[k].u])
19         dfs1(g[k].u);
20     q[++t]=u;
21     return ;    
22 }
23 void dfs2(int u,int t)
24 {
25     vis[u]=true;
26     mark[u]=t;
27     for (int k=firp[u];k;k=gp[k].nex)
28       if (!vis[gp[k].u])
29         dfs2(gp[k].u,t);
30     return;    
31 }
32 void scc()
33 {
34     int i;
35     for (i=1;i<=n;i++)
36       if (!vis[i])
37         dfs1(i);
38     for (i=0;i<=n;i++)
39       vis[i]=false;
40     for (i=n;i>=1;i--)
41       if (!vis[q[i]])
42         dfs2(q[i],++s);
43     return;          
44 }
45 int main()
46 {
47     int i,j,k,x,y;
48     scanf("%d%d",&n,&m);
49     for (i=1;i<=m;i++)
50       scanf("%d%d",&x,&y),
51       ADD(++t,x,y);
52     t=0;
53     scc();
54     printf("%d",s);  //  输出强连通分量个数 
55     return 0;
56 }
View Code

(2)tarjan

1 #include <cstdio>
 2 struct note{
 3     int x,nex;
 4 };
 5 note g[8005];
 6 int fir[3005],stack[3005],dfn[3005],low[3005],zone[3005],ind[3005];
 7 int m,n,a,b,s,t,p,num;
 8 long long mark[3005];
 9 bool vis[3005];   //  标记结点是否在栈里 
10 void ADD(int k,int x,int y)
11 {
12     g[k].x=y;   g[k].nex=fir[x];   fir[x]=k;
13 }
14 void tarjan(int u)
15 {
16     stack[++t]=u;
17     vis[u]=true;
18     low[u]=dfn[u]=++s;
19     for (int k=fir[u];k;k=g[k].nex)
20     {
21         int v=g[k].x;
22         if (!dfn[v])
23         {
24             tarjan(v);
25             if (low[v]<low[u])
26               low[u]=low[v];
27         }
28         else
29           if (vis[v] && dfn[v]<low[u])
30             low[u]=dfn[v];
31     }
32     if (low[u]==dfn[u])   //  找到一个强连通分量 
33     {
34         num++;  int v,tt=t;
35         do
36         {
37             v=stack[t];
38             vis[v]=false;
39             zone[v]=num;   //  标记结点所属强连通分量
40             t--;
41         }while (u!=v);
42     }
43     return;
44 }
45 int main()
46 {
47     int i,j,k;
48     long long x;
49     scanf("%d",&n);  
50     scanf("%d",&m);
51     for (i=1;i<=m;i++)
52     {
53         scanf("%d%d",&a,&b);
54         ADD(++t,a,b);
55     }
56     t=0;  
57     for (i=1;i<=n;i++)
58       if (!dfn[i])
59         tarjan(i);
60     for (i=1;i<=n;i++)           // 缩点 
61       for (k=fir[i];k;k=g[k].nex)      
62       {
63             int v=g[k].x;
64             if (zone[i]!=zone[v])
65                ind[zone[v]]++; 
66       }
67     return 0;
68 }
 
View Code

 

4、割点与桥

 1 void tarjan(int u,int fa)  
 2 {  
 3     int cnt=0;  
 4     low[u]=dfn[u]=++idx;  
 5     for(int i=0;i<(int)adj[u].size();i++)  
 6     {  
 7         int v=adj[u][i];  
 8         if(v==fa) continue;  
 9         if(!dfn[v])   
10         {  
11             tarjan(v,u);  
12             ++cnt;  
13             low[u]=min(low[u],low[v]);  
14             if( (root==u&&cnt>1)||(root!=u&&dfn[u]<=low[v]) ) //判断是否是割点  
15                 isap[u]=1;  
16             if(dfn[u]<low[v]) cutE[++numE]=Edge(u,v);//判断是否是桥,视具体情况采用恰当的结构记录。  
17         }  
18         else low[u]=min(low[u],dfn[v]);//这里不用判断是否点v在栈中  
19     }  
20 }  
View Code

 
5、点双连通分量

  1 /*无向图的双连通分量:
  2 
  3 割顶的bccno无意义:割点的bccno会被多次赋值,所以//它的值无意义。
  4 
  5 调用结束后, S保证为空:
  6 对于点双连通分支,实际上在求割点的过程中就能顺便把每个点双连通分支求出。
  7 建立一个栈,存储当前双连通分支,在搜索图时,每找到一条树枝边或后向边(非横叉边),
  8 就把这条边加入栈中。如果遇到某时满足DFS(u)<=Low(v),说明u是一个割点,
  9 同时把边从栈顶一个个取出,直到遇到了边(u,v),取出的这些边与其关联的点,
 10 组成一个点双连通分支。割点可以属于多个点双连通分支,其余点和每条边只属于且
 11 属于一个点双连通分支。*/
 12  
 13 #include <iostream>
 14 #include <cstdlib>
 15 #include <cstdio>
 16 #include <algorithm>
 17 #include <cstring>
 18 #include <stack>
 19 #include <vector>
 20 #include <queue>
 21 #include <map>
 22 
 23 using namespace std;
 24 
 25 const int maxn = 6;
 26 
 27 int pre[maxn], iscut[maxn], bccno[maxn], low[maxn],dfs_clock, bcc_cnt;
 28 vector<int> G[maxn], bcc[maxn];
 29 
 30 struct Edge{
 31     int u, v;
 32 };
 33 stack<Edge> S;
 34 int dfs(int u, int fa){
 35     int lowu = pre[u] = ++dfs_clock;
 36     int child = 0;
 37    // printf("u%d\n",u);
 38     for(int i=0; i<G[u].size(); i++){
 39         int v = G[u][i];
 40         Edge e = (Edge){u, v};
 41         if(!pre[v]){
 42             S.push(e);
 43             child++;
 44             int lowv = dfs(v, u);
 45             lowu = min(lowu, lowv);
 46             if(lowv >= pre[u]){
 47                 iscut[u] = true;
 48                 bcc_cnt++; bcc[bcc_cnt].clear();
 49                 for(;;)
 50                 {
 51                     Edge x = S.top(); S.pop();
 52                     if(bccno[x.u] != bcc_cnt) 
 53            {
 54                         bcc[bcc_cnt].push_back(x.u);
 55                         bccno[x.u] = bcc_cnt;
 56                     }
 57                     if(bccno[x.v] != bcc_cnt) {
 58                         bcc[bcc_cnt].push_back(x.v);
 59                         bccno[x.v] = bcc_cnt;
 60                     }
 61                     if(x.u == u && x.v == v) break;
 62                 }
 63             }
 64         }
 65         else if(pre[v] < pre[u] && v != fa){
 66             S.push(e);
 67             lowu = min(lowu, pre[v]);
 68            // printf("fan lowu%d\n",lowu);
 69            // printf("fan%d %d\n",e.u,e.v);
 70         }
 71     }
 72     if(fa < 0 && child == 1) iscut[u] = 0;
 73     low[u]=lowu;
 74     return lowu;
 75 }
 76 
 77 void find_bcc(int n){
 78     memset(pre, 0, sizeof(pre));
 79     memset(iscut, 0, sizeof(iscut));
 80     memset(bccno, 0, sizeof(bccno));
 81     dfs_clock = bcc_cnt = 0;
 82     for(int i=0; i<n; i++){
 83         if(!pre[i]) dfs(i, -1);
 84     }
 85 }
 86 
 87 int main(){
 88     int m, u, v, n;
 89     freopen("test2.in","r",stdin);
 90     scanf("%d%d", &n, &m);
 91 
 92     for(int i=0; i<m; i++){
 93         cin>>u>>v;
 94         G[u].push_back(v);
 95         G[v].push_back(u);
 96     }
 97 
 98     find_bcc(n);
 99 
100     printf("%d\n", bcc_cnt);    //双连通分量的个数
101     for(int i=1; i<=bcc_cnt; i++){  //输出每个双连通分量
102         for(int j=0; j<bcc[i].size(); j++){
103             printf("%d ", bcc[i][j]);
104         }
105         putchar('\n');
106     }
107   
108     return 0;
109 }
View Code

 

6、边双连通分量

 1 //边双连通分量的求解非常简单,因为边双连通分量之间没有公共边,而且桥不在任意一个边双连通分量中,所以算法十分简单,即先一次DFS找到所有桥,再一次DFS(排除了桥)找到边双连通分量。 
 2 //PS:当然可以用一次DFS实现。 
 3 struct Edge{
 4     int u,v;
 5     Edge(int u=0,int v=0):u(u),v(v){}
 6 }e[maxm];
 7 int n,m,stamp,dfn[maxn],low[maxn],bccno[maxn],bcc_cnt;
 8 vector<int> vec[maxn],bcc[maxn];
 9 bool g[maxn][maxn],isbridge[maxm];
10 
11 void tarjan(int u,int fa)
12 {
13     int tmp;
14     dfn[u]=low[u]=++stamp;
15     for(int i=0;i<vec[u].size();i++)
16     {
17         tmp=e[vec[u][i]].v;
18         if(!dfn[tmp])
19         {
20             tarjan(tmp,u);
21             low[u]=min(low[u],low[tmp]);
22             if(low[tmp]>dfn[u])
23                 isbridge[vec[u][i]]=isbridge[vec[u][i]^1]=1;
24         }
25         else if(dfn[tmp]<dfn[u] && tmp!=fa)
26         {
27             low[u]=min(low[u], dfn[tmp]);
28         }
29     }
30 }
31 
32 void dfs(int u)
33 {
34     dfn[u]=1;
35     bccno[u]=bcc_cnt;
36     for(int i=0;i<vec[u].size();i++)
37     {
38         int tmp=vec[u][i];
39         if(isbridge[tmp])
40             continue;
41         if(!dfn[e[tmp].v])
42         {
43             dfs(e[tmp].v);
44         }
45     }
46 }
47 
48 void find_ebcc(){
49     bcc_cnt=stamp=0;
50     memset(dfn,0,sizeof(dfn));
51     memset(low,0,sizeof(low));
52     memset(isbridge,0,sizeof(isbridge));
53     memset(bccno,0,sizeof(bccno));
54     memset(bcc,0,sizeof(bcc));
55     for(int i=1;i<=n;i++)
56         if(!dfn[i])
57             tarjan(i, -1);
58     memset(dfn,0,sizeof(dfn));
59     for(int i=1;i<=n;i++)
60     {
61         if(!dfn[i])
62         {
63             bcc_cnt++;
64             dfs(i);
65         }
66     }               
67 }
View Code

 

二、数论

1、最大公因数

1 int gcd(int a,int b)
2 {
3     return b?gcd(b,a%b):a;
4 }
View Code

 

2、最小公倍数

1 int gcd(int a,int b)
2 {
3     return b?gcd(b,a%b):a;
4 }
5 int lcm(int a,int b)
6 {
7     return a*b/gcd(a,b);
8 }
View Code

 

3、快速幂(ab

 1 #include <cstdio>
 2 #define ll long long
 3 const int maxn=1e9+7;
 4 ll ksm(int a,int b)
 5 {
 6     ll s=1;
 7     while (b)
 8     {
 9         if (b&1) s=s*a%maxn;
10         a=1ll*a*a%maxn;
11         b>>=1;
12     }
13     return s;
14 }
View Code

 

4、欧拉筛法求素数

 1 #include <cstdio>
 2 int p[100005],pt;   // 存素数 
 3 bool f[100005];
 4 void makeprime()
 5 {
 6     int i,j;
 7     for (i=2;i<=100005;i++)
 8     {
 9         if (!f[i]) p[++pt]=i;
10         for (j=1;j<=pt && 1ll*i*p[j]<=100005;j++)
11         {
12             f[i*p[j]]=1;
13             if (!(i%p[j])) break;
14         }
15     }
16 //    for (i=1;i<=pt;i++) printf("%d ",p[i]); 
17     return;
18 }
19 int main()
20 {
21     makeprime();
22     return 0;
23 }
View Code

 

5、逆元求组合数

 1 #include <cstdio>
 2 #define ll long long
 3 const ll maxn=1e9+7;
 4 int n,m,K;
 5 ll ans,fac[900005],inv[900005];
 6 ll C(int n,int m)  //  n>=m 
 7 {
 8     return fac[n]*inv[m]%maxn*inv[n-m]%maxn;
 9 }
10 ll ksm(int a,int b)
11 {
12     ll s=1;
13     while (b)
14     {
15         if (b&1) s=s*a%maxn;
16         a=1ll*a*a%maxn;
17         b>>=1;
18     }
19     return s;
20 }
21 int main()
22 {
23     int i,j;
24     scanf("%d%d",&n,&m);
25     for (fac[0]=inv[0]=i=1;i<900005;i++) fac[i]=fac[i-1]*i%maxn;
26     inv[900004]=ksm(fac[900004],maxn-2);
27     for (i=900004;i>=1;i--) inv[i]=inv[i+1]*(i+1)%maxn;
28     printf("%lld\n",C(n,m));
29     return 0;
30 }
View Code

 

6、杨辉三角求组合数

1 #include <cstdio>
 2 const int maxn=1e9+7;
 3 int c[1005][1005];
 4 int main()
 5 {
 6     int i,j;
 7     c[0][0]=1;
 8     for (i=1;i<=1000;i++) c[i][0]=c[i][i]=1;
 9     for (i=2;i<=1000;i++)
10       for (j=1;j<i;j++)
11         c[i][j]=(c[i-1][j]+c[i-1][j-1])%maxn;
12 /*    for (i=0;i<=10;i++)
13     {
14         for (j=0;j<=i;j++) printf("%d ",c[i][j]);
15         printf("\n");
16     } */
17     return 0;
18 }
View Code

 

7、埃氏筛法求欧拉函数

 1 #include <cstdio>
 2 #define ll long long
 3 int eul[10000005],m;
 4 int main()
 5 {
 6     int i,j;
 7     scanf("%d",&m);  // 1~m 的欧拉函数 
 8     for (i=1;i<=m;i++) eul[i]=i;  
 9     for (i=2;i<=m;i++)
10       if (eul[i]==i)
11         for (j=i;j<=m;j+=i)
12           eul[j]=eul[j]/i*(i-1);
13     return 0;    
14 }
View Code

 

8、质因数分解求欧拉函数

1 #include <cstdio>
 2 #define ll long long
 3 int eul[10000005],n;
 4 ll euler_phi(int n)
 5 {
 6     ll s=n;
 7     for (int i=2;i*i<=n;i++)
 8       if (!(n%i))
 9         for (s=s/i*(i-1);!(n%i);n/=i);
10       if (n!=1) s=s/n*(n-1);
11       return s;
12 }
13 int main()
14 {
15     int i,j;
16     scanf("%d",&n);  
17     printf("%lld",euler_phi(n));
18     return 0;    
19 }
View Code

 

9、扩展欧几里得(ax+by=c的一组特解x,y)

 1 int exgcd(int a,int b,int &x,int &y)
 2 {
 3     if (!b) 
 4     {
 5         x=1,y=0;
 6         return a;
 7     }
 8     int ans=exgcd(b,a%b,x,y);
 9     t=x,x=y,y=t-(a/b)*y;
10     return ans;
11 }
View Code

 

三、数据结构

1、单调队列

 1 #include <cstdio>
 2 int n,m,a[1000005];
 3 int q1[1000005],h1,t1,s1[1000005],p1,d1[1000005];  // 求定长滑动区间内的最大值 
 4 int q2[1000005],h2,t2,s2[1000005],p2,d2[1000005];  // 求定长滑动区间内的最小值
 5 int main()
 6 {
 7     int i,j,x;
 8     scanf("%d%d",&n,&m);
 9     scanf("%d",&x);
10     q1[1]=q2[1]=x;
11     h1=h2=t1=t2=d1[1]=d2[1]=1;
12     for (i=2;i<=m;i++)
13     {
14         scanf("%d",&x);
15         while (q1[t1]<=x && t1>=h1) t1--;
16         q1[++t1]=x;  d1[t1]=i;
17         
18         while (q2[t2]>=x && t2>=h2) t2--;
19         q2[++t2]=x;  d2[t2]=i;
20     }
21     s1[1]=q1[1];  s2[1]=q2[1];
22     p1=p2=1;
23     for (i=m+1;i<=n;i++)
24     {
25         scanf("%d",&x);
26         while (q1[t1]<=x && t1>=h1) t1--;
27         q1[++t1]=x;  d1[t1]=i;
28         while (i-d1[h1]>=m) h1++;
29         s1[++p1]=q1[h1];
30         
31         while (q2[t2]>=x && t2>=h2) t2--;
32         q2[++t2]=x;  d2[t2]=i;
33         while (i-d2[h2]>=m) h2++;
34         s2[++p2]=q2[h2];
35     }
36     for (i=1;i<=p2;i++)
37       printf("%d ",s2[i]);
38     printf("\n");
39     
40     for (i=1;i<=p1;i++)
41       printf("%d ",s1[i]);
42     return 0;
43 }
View Code

 

2、字典树

 1 #include <cstdio>
 2 #define ll long long
 3 int n,cnt=1,f[12000015][2],num[12000015];   //  树的深度 * 每个结点分叉数 * 字符个数 
 4 ll a[100005],ans;
 5 void add(ll x)
 6 {
 7     int now=1,i,j;
 8     for (i=0;i<60;i++)
 9     {
10         j=((x&(1ll<<i))>>i);
11         if (!f[now][j]) f[now][j]=++cnt;
12         num[f[now][j]]++;
13         now=f[now][j];
14     }
15     return;
16 }
17 void query(ll x)
18 {
19     int now=1,k,j;
20     for (now=1,j=0;j<60;j++)
21     {
22         k=((x&(1ll<<j))>>j);
23         ans+=num[f[now][k]];
24         now=f[now][k];
25       }
26       return;
27 }
28 int main()
29 {
30     int i,j,k,now;
31     scanf("%d",&n);
32     for (i=1;i<=n;i++)
33       scanf("%lld",&a[i]);
34     for (i=1;i<=n;i++) add(a[i]);
35     for (i=1;i<=n;i++) query(a[i]);
36       printf("%lld\n",ans);
37       return 0;
38 }
View Code

 

3、树状数组

 1 #include <cstdio>
 2 int n,m,k,a[100005],c[100005];
 3 int lowbit(int x)
 4 {
 5     return x&(-x);
 6 }
 7 void plus(int p,int x)
 8 {
 9     while (p<=n)
10       c[p]+=x,
11       p+=lowbit(p);
12     return;
13 }
14 int getsum(int p)
15 {
16     int s=0;
17     while (p)
18       s+=c[p],
19       p-=lowbit(p);
20     return s;
21 }
22 int main()
23 {
24     int i,j,x,y;
25     scanf("%d%d",&n,&m);
26     for (i=1;i<=n;i++)
27       scanf("%d",&a[i]),
28       plus(i,a[i]);
29     while (m--)
30     {
31         scanf("%d%d%d",&k,&x,&y);     
32         //  k=0  求区间[x,y]的和  
33         //  k=1  a[x]的值加上y 
34         if (k) plus(x,y);
35         else printf("%d\n",getsum(y)-getsum(x-1));
36     }
37     return 0;
38 } 
View Code

 

4、线段树

 1 #include <cstdio>
 2 int n,m,s,t,p,f[4000005],a[1000005];   //  f[4*n] 
 3 void build(int l,int r,int id)
 4 {
 5     if (l==r)
 6     {
 7         f[id]=a[l];
 8         return;
 9     }
10     int ls=id<<1,rs=ls|1,mid=(l+r)>>1;
11     build(l,mid,ls);
12     build(mid+1,r,rs);
13     f[id]=f[ls]+f[rs];
14     return;
15 }
16 void modify(int l,int r,int id)
17 {
18     if (l==r)
19     {
20         f[id]+=t;
21         return;
22     }
23     int ls=id<<1,rs=ls|1,mid=(l+r)>>1;
24     if (s<=mid) modify(l,mid,ls);
25     else modify(mid+1,r,rs);
26     f[id]=f[ls]+f[rs];
27     return;
28 }
29 int query(int l,int r,int id)
30 {
31     if (s<=l && r<=t) return f[id];
32     int sum=0,ls=id<<1,rs=ls|1,mid=(l+r)>>1;
33     if (s<=mid) sum=query(l,mid,ls);
34     if (t>mid) sum+=query(mid+1,r,rs);
35     return sum;
36 }
37 int main()
38 {
39     int i,j;
40     scanf("%d%d",&n,&m);
41     build(1,n,1);
42     while (m--)
43     {
44         scanf("%d%d%d",&p,&s,&t);
45         //  p=0  a[s]的值加上t
46         //  p=1  求区间[s,t]的和 
47         if (!p) modify(1,n,1);
48         else printf("%d\n",query(1,n,1));
49     }
50     return 0;
51 }
View Code

 

四、动态规划

1、01背包

(1)二维

 1 #include <cstdio>
 2 int n,m,w[1005],c[1005],f[1005][1005];
 3 int max(int x,int y)
 4 {
 5     return x>y?x:y;
 6 }
 7 int main()
 8 {
 9     int i,j,k;
10     scanf("%d%d",&n,&m);
11     for (i=1;i<=n;i++)
12       scanf("%d%d",&w[i],&c[i]);
13     for (i=1;i<=n;i++)
14       for (j=0;j<=m;j++)
15       {
16           f[i][j]=f[i-1][j];
17           if (j>=w[i]) f[i][j]=max(f[i][j],f[i-1][j-w[i]]+c[i]);
18       }   
19     printf("%d",f[n][m]);
20     return 0;
21 }
View Code

(2)一维

 1 #include <cstdio>
 2 int n,m,w[1005],c[1005],f[1005];
 3 int max(int x,int y)
 4 {
 5     return x>y?x:y;
 6 }
 7 int main()
 8 {
 9     int i,j,k;
10     scanf("%d%d",&n,&m);
11     for (i=1;i<=n;i++)
12       scanf("%d%d",&w[i],&c[i]);
13     for (i=1;i<=n;i++)
14       for (j=m;j>=w[i];j--)
15         f[j]=max(f[j],f[j-w[i]]+c[i]);  
16     printf("%d",f[m]);
17     return 0;
18 }
View Code

 

2、完全背包

 1 #include <cstdio>
 2 int n,m,w[1005],c[1005],f[1005];
 3 int max(int x,int y)
 4 {
 5     return x>y?x:y;
 6 }
 7 int main()
 8 {
 9     int i,j,k;
10     scanf("%d%d",&n,&m);
11     for (i=1;i<=n;i++)
12       scanf("%d%d",&w[i],&c[i]);
13     for (i=1;i<=n;i++)
14       for (j=w[i];j<=m;j++)
15         f[j]=max(f[j],f[j-w[i]]+c[i]);  
16     printf("%d",f[m]);
17     return 0;
18 }
View Code

 

3、多重背包

(1)普通二维

 1 #include <cstdio> 
 2 int n,m,w[1005],v[1005],num[1005],f[1005][2005];
 3 int min(int x,int y)
 4 {
 5     return x<y?x:y;
 6 }
 7 int max(int x,int y)
 8 {
 9     return x>y?x:y;
10 }
11 int main()
12 {
13     int i,j,k,t;
14     scanf("%d%d",&n,&m);
15     for (i=1;i<=n;i++) 
16       scanf("%d%d%d",&w[i],&v[i],&num[i]);
17     for(i=1;i<=n;i++)
18       for(j=w[i];j<=m;j++)
19       {
20         t=min(num[i],j/w[i]);//可以放的个数
21         for(k=0;k<=t;k++)
22           f[i][j]=max(f[i][j],f[i-1][j-k*w[i]]+k*v[i]);
23       }
24     printf("%d",f[n][m]);
25     return 0;
26 }
View Code

(2)一维

 1 #include <cstdio> 
 2 int n,m,w[1005],v[1005],num[1005],f[2005];
 3 int min(int x,int y)
 4 {
 5     return x<y?x:y;
 6 }
 7 int max(int x,int y)
 8 {
 9     return x>y?x:y;
10 }
11 int main()
12 {
13     int i,j,k,t;
14     scanf("%d%d",&n,&m);
15     for (i=1;i<=n;i++) 
16       scanf("%d%d%d",&w[i],&v[i],&num[i]);
17     for(i=1;i<=n;i++)
18     {
19         t=min(num[i],j/w[i]);//可以放的个数
20         for(k=0;k<=t;k++)
21           for(j=m;j>=w[i]*k;j--)
22             f[j]=max(f[j],f[j-k*w[i]]+k*v[i]);
23     }
24     printf("%d",f[m]);
25     return 0;
26 }
View Code

(3)二进制优化

 1 #include <cstdio>
 2 int n,m,count,w[105],v[105],num[105],f[100005];
 3 int max(int x,int y)
 4 {
 5     return x>y?x:y;
 6 }
 7 int main()
 8 {
 9     int i,j,p,g;
10     scanf("%d%d",&n,&m);
11     for(i=1;i<=n;i++)
12       scanf("%d%d%d",&w[i],&v[i],&num[i]);
13     for(i=1;i<=n;i++)
14     {
15         p=g=0;
16         while(num[i]>g)
17         {
18             for(j=m;j>=w[i]*g;j--)
19               f[j]=max(f[j],f[j-w[i]*g]+v[i]*g);
20             num[i]-=g;  g=1<<p;  p++;
21         }
22         for(j=m;j>=w[i]*num[i];j--)
23           f[j]=max(f[j],f[j-w[i]*num[i]]+v[i]*num[i]);
24     }
25     printf("%d",f[m]);
26     return 0;
27 }
View Code

 

4、最长不下降子序列

(1)O(n2)

 1 #include <cstdio>
 2 int n,a[40005],f[40005],ans;
 3 int main()
 4 {
 5     int i,j;
 6     scanf("%d",&n);
 7     for (i=1;i<=n;i++) scanf("%d",&a[i]);
 8     f[1]=1;
 9     for (i=2;i<=n;i++)
10     {
11         for (j=1;j<i;j++)
12           if (a[j]<=a[i] && f[j]>f[i])
13             f[i]=f[j];
14         f[i]++;
15     }
16     for (i=1;i<=n;i++)
17       if (f[i]>ans)
18         ans=f[i];
19     printf("%d\n",ans);    
20     return 0;
21 }
View Code

(2)O(n log n)

 1 #include <algorithm>
 2 #include <cstdio>
 3 int n,a[40005],d[40005];
 4 int main()
 5 {
 6     int i,j,len=1;
 7     scanf("%d",&n);
 8     for (i=1;i<=n;i++) scanf("%d",&a[i]);
 9     d[1]=a[1];  //初始化 
10     for (i=2;i<=n;i++)
11     {
12         if (a[i]>=d[len]) d[++len]=a[i];  //如果可以接在len后面就接上,如果是最长上升子序列,这里变成> 
13         else  //否则就找一个最该替换的替换掉 
14         {
15             j=std::upper_bound(d+1,d+len+1,a[i])-d;  //找到第一个大于它的d的下标,如果是最长上升子序列,这里变成lower_bound 
16             d[j]=a[i]; 
17         }
18     }
19     printf("%d\n",len);    
20     return 0;
21 }
View Code

 

5、最长公共子序列

(1)普通

 1 #include <cstring>
 2 #include <cstdio>
 3 char a[1005],b[1005];
 4 int lena,lenb,f[1005][1005];
 5 int max(int x,int y)
 6 {
 7     return x>y?x:y;
 8 }
 9 int main()
10 {
11     int i,j;
12     scanf("%s%s",a,b);
13     lena=strlen(a);
14     lenb=strlen(b);
15     f[0][0]=(a[0]==b[0]);
16     for(i=1;i<=lena;i++)
17       for(j=1;j<=lenb;j++)
18       {
19         if(a[i-1]==b[j-1])
20           f[i][j]=f[i-1][j-1]+1;
21         else
22           f[i][j]=max(f[i-1][j],f[i][j-1]);
23       }
24     printf("%d\n",f[lena][lenb]);
25     return 0;
26 }
View Code

(2)打印路径

 1 #include<cstring>
 2 #include<cstdio>
 3 char a[1005],b[1005];
 4 int f[1005][1005],lena,lenb,flag[1005][1005];
 5 void write(int i,int j)
 6 {
 7     if(i==0||j==0) return;  //递归终止条件
 8     if(!flag[i][j])
 9     {
10         write(i-1,j-1);
11         printf("%c",a[i-1]);
12     }
13     else if(flag[i][j]==1)
14     {
15         write(i-1,j);
16     }
17     else if(flag[i][j]=-1)
18     {
19         write(i,j-1);
20     }
21 }
22 int main()
23 {
24     int i,j;
25     scanf("%s%s",a,b);
26     lena=strlen(a);
27     lenb=strlen(b);
28     for(i=1;i<=lena;i++)
29       for(j=1;j<=lenb;j++)
30       {
31         if(a[i-1]==b[j-1])
32         {
33             f[i][j]=f[i-1][j-1]+1;
34             flag[i][j]=0;///来自于左上方
35         }
36         else
37         {
38             if(f[i-1][j]>f[i][j-1])
39             {
40                 f[i][j]=f[i-1][j];
41                 flag[i][j]=1;///来自于左方
42             }
43             else
44             {
45                 f[i][j]=f[i][j-1];
46                 flag[i][j]=-1;///来自于上方
47             }
48         }
49     }
50     write(lena,lenb);
51     return 0;
52 }
View Code

 

6、区间动规

1 int dp(int l,int r)
2 {
3     if (used[l][r]) return f[l][r];
4     used[l][r]=1;
5     if (l==r) return f[l][r]=0;
6     for (int i=l;i<r;i++)    
7         f[l][r]=min(f[l][r],dp(l,i)+dp(i+1,r)+w[l][r]);      
8     return f[l][r];    
9 }
View Code

 

五、高精度

1、高精加高精

 1 #include <cstring>
 2 #include <cstdio>
 3 struct note{
 4     int len,v[1005];
 5 };
 6 int max(int x,int y)
 7 {
 8     return x>y?x:y;
 9 }
10 note operator + (note a,note b)
11 {
12     note c;
13     memset(c.v,0,sizeof(c.v));
14     int i,lenc=max(a.len,b.len);
15     for (i=1;i<=lenc;i++)
16       c.v[i]+=a.v[i]+b.v[i],
17       c.v[i+1]+=c.v[i]/10,
18       c.v[i]%=10;
19     while (c.v[lenc+1]) lenc++;
20     c.len=lenc;
21     return c;
22 }
View Code

 

2、高精减高精

 1 #include <cstdio>
 2 struct note{
 3     int len,v[10005];
 4 };
 5 char s1[10005],s2[10005];
 6 bool operator < (note a,note b)
 7 {
 8     if (a.len!=b.len) return a.len<b.len;
 9     for (int i=a.len;i>=1;i--)
10       if (a.v[i]!=b.v[i])
11         return a.v[i]<b.v[i];
12     return 0;
13 }
14 note operator - (note a,note b)
15 {
16     note c;
17     int fg=1;
18     if (a<b) fg=-1,c=a,a=b,b=c;
19     int i,lenc=a.len;
20     for (i=1;i<=lenc;i++)
21     {
22         if (a.v[i]<b.v[i]) a.v[i]+=10,a.v[i+1]--;
23         c.v[i]=a.v[i]-b.v[i];
24     }
25     while (!c.v[lenc] && lenc>1) lenc--;
26     c.len=lenc;
27     c.v[lenc]*=fg;
28     return c;
29 }
View Code

 

3、高精乘单精

 1 #include <cstdio>
 2 struct note{
 3     int v[1000],len;
 4 };
 5 note operator * (note a,int b)
 6 {
 7     note c;
 8     int w=0;
 9     int i,lena=a.len,lenc;
10     for (i=1;i<=lena;i++)
11       c.v[i]=a.v[i]*b+w,
12       w=c.v[i]/10,
13       c.v[i]%=10;
14     for(lenc=lena;w;c.v[++lenc]=w%10,w/=10);
15     c.len=lenc;
16     return c;
17 }
View Code

 

4、高精乘高精

 1 #include <cstring>
 2 #include <cstdio>
 3 struct note{
 4     int len,v[10005];
 5 };
 6 note operator * (note a,note b)
 7 {
 8    note c;
 9    memset(c.v,0,sizeof(c.v));
10    int i,j,lena=a.len,lenb=b.len,lenc=a.len+b.len-1;
11    for (i=1;i<=lena;i++)
12       for (j=1;j<=lenb;j++)
13          c.v[i+j-1]+=a.v[i]*b.v[j];
14    for (i=1;i<=lenc;i++)
15       c.v[i+1]+=c.v[i]/10,
16       c.v[i]%=10;
17    if (c.v[lenc+1]) lenc++;
18    for (;c.v[lenc]>=10;lenc++) c.v[lenc+1]=c.v[lenc]/10,c.v[lenc]%=10;
19      c.len=lenc;
20    return c;
21 }
View Code

 

5、高精除单精

 1 #include <cstdio>
 2 struct note{
 3     int v[1000],len;
 4 };
 5 note operator / (note a,int b)
 6 {
 7     note c;
 8     int i,lena=a.len,lenc=1,x=0,t;
 9     for (i=lena,x=a.v[lena];x<b && i>1;x=x*10+a.v[--i]);
10     c.v[1]=x/b;  x%=b;
11     for (i--;i>=1;i--)
12       x=x*10+a.v[i],
13       c.v[++lenc]=x/b,
14       x%=b;
15     for (i=1;i<=lenc/2;i++)
16       c.v[i]^=c.v[lenc-i+1],c.v[lenc-i+1]^=c.v[i],c.v[i]^=c.v[lenc-i+1];
17     c.len=lenc;
18     return c;
19 }
View Code

 

六、其它

1、读入优化

1 int read()
2 {
3     int s=0;
4     char ch=getchar();
5     while (ch<'0' || ch>'9') ch=getchar();
6     while (ch>='0' && ch<='9') 
7       s=s*10+ch-'0',ch=getchar();
8     return s;
9 }
View Code

 

2、输出优化

1 void write(int x)
2 {
3     if (x>=10) write(x/10);
4     putchar(x%10+'0');
5     return;
6 }
View Code

 

3、倍增LCA

 1 #include <cstdio>
 2 struct node{
 3     int u,v,nex;
 4 }g[1000005];
 5 int n,Q,root,fir[500005],num,f[500005][20],d[500005];
 6 void add(int x,int y)
 7 {
 8     g[++num].u=y;  g[num].nex=fir[x];  fir[x]=num;
 9     return;
10 }
11 void dfs(int x,int fa)
12 {
13     int i,k,v;
14     f[x][0]=fa;  d[x]=d[fa]+1;
15     for (i=1;i<=19;i++)
16       f[x][i]=f[f[x][i-1]][i-1];
17     for (k=fir[x];k;k=g[k].nex)
18     {
19         v=g[k].u;
20         if (v==fa) continue;
21         dfs(v,x);
22     }
23     return;
24 }
25 int lca(int x,int y)
26 {
27     int i,j;
28     if (d[x]>d[y]) x^=y,y^=x,x^=y;
29     for (i=19;i>=0;i--)
30       if (d[f[y][i]]>=d[x])
31         y=f[y][i];
32     if (x==y) return x;
33     for (i=19;i>=0;i--)
34       if (f[x][i]!=f[y][i])
35         x=f[x][i],y=f[y][i];
36     return f[x][0];
37 }
38 int main()
39 {
40     int i,j,k,x,y;
41     scanf("%d%d%d",&n,&Q,&root);
42     for (i=1;i<n;i++)
43       scanf("%d%d",&x,&y),
44       add(x,y),add(y,x);
45     dfs(root,0);
46     while (Q--)
47     {
48         scanf("%d%d",&x,&y);
49         printf("%d\n",lca(x,y));
50     }
51     return 0;
52 }
View Code

 

4、计时函数

 1 #include <cstdio>
 2 #include <ctime>
 3 int main()
 4 {
 5     clock_t st, ed;
 6     st=clock();
 7     for(int i=0;i<100000000;i++)
 8     {
 9         i-=1;    i+=1;
10     }
11     ed=clock();
12     printf("Total time:%.2fs",(double)(ed-st)/CLOCKS_PER_SEC); 
13     return 0;
14 }
View Code

 

暂存

 1 #include <cstdio>
 2 #include <set>
 3 #define ll long long
 4 std::set<int> s;
 5 std::set<int>::iterator p;
 6 int n,op,x,k,cnt[100005];
 7 ll ans;
 8 int main()
 9 {
10     scanf("%d",&n);
11     while (n--)
12     {
13         scanf("%d%d",&op,&x);
14         if (op==1)
15         {
16             ans+=x;
17             if (s.empty()) continue;
18             p=s.lower_bound(x);
19             if (p==s.begin()) continue;
20             k=*(--p);
21             ans-=k;
22             cnt[k]--;
23             if (!cnt[k]) s.erase(k);
24         }
25         else s.insert(x),cnt[x]++;
26     }
27     printf("%lld\n",ans);
28     return 0;
29 }
View Code

 

转载于:https://www.cnblogs.com/rabbit1103/p/9702576.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值