zoukankan      html  css  js  c++  java
  • 常见数据结构/算法模板


    title: 常见数据结构/算法模板
    date: 2020-08-20
    categories: acm
    tags: acm
    top: true

    0. to start with

    remembering one trick is better than recording a hundred.

    包含一些模板和例题

    技巧,STL,函数,细节,参考资料(比如背包九讲)等见 https://www.cnblogs.com/lqerio/p/13484897.html

    1. DP Dynamic Programming

    如果前面的结果可以被利用,就可以dp。
    先写状态转移方程,边界条件,初始结束状态的设置。
    如果数据计算量大可以预处理。

    woj1023.
    dp 状态转移方程: f[i]=min(f[i],f[j]+valuecluser[j+1][i])(i-j>=p)  //j+1...注意分界点 dp[0]=0.i in range p-1-N (编号为1-n)
    //dp注意初始状态结束状态预处理。f[0]=0,f[i]初始为maxd
    预处理:计算valuecluster[i][j]
    

    1.1 Pack 背包

    1.1.1 01背包

    WOJ1005
    const int maxn=10005;
    int value[maxn];
    int sizee[maxn];
    int final[100005];
    for(int i=0;i<=noah;i++) final[i]=0;  
        for(int i=0;i<n;i++)
            for(int j=noah;j>0;j--)   //倒序理解就是01背包只有一件,前i-1件已经判断完了,只判断这一件,在比较小的情况下放不影响在比较大的情况放
                if(j>=sizee[i])         //final可行因为如果小的能放大的也能放。
                    final[j]=max(final[j],final[j-sizee[i]]+value[i]);
            cout<<final[noah]<<endl;
        }
    

    1.2 剪枝 / 回溯

    还是待更新!!!!
    下面的不全
    
    剪枝
    1.最优化剪枝:如果当前已经找到的最优路径长度为L ,那么在继续搜索的过程中,总长度已经大于等于L的走法,就可以直接放弃,不用走到底了
    
    2.可行性剪枝:如果当前到达城市的路费已大于k,或者等于k且没有到达终点,就可以直接放弃。
    
    回溯
    
    used[i] = 1;//设为用过 
                dfs(u + 1);//下一个数字 
                used[i] = 0;//回溯:回到没用过 
    			
    

    1.3 方格&&滚动数组&&优化时间

    见我的woj1012题解

    2. DFS

    2.1 recursive

    PAT 1004
    #include<iostream>
    #include<queue>
    #include<vector>
    
    using namespace std;
    vector<int>nodes[100];
    int ans[105];
    int level;
    void dfs(int id,int depth){
        level=max(level,depth);
        int temp=id;
            if(nodes[temp].size()==0){
                ans[depth]++;
            }
            else{
                for(int i=0;i<nodes[temp].size();i++){
                    dfs(nodes[temp][i],depth+1);
                }
            }
    }
    
    int main(){
        int n,m;
        cin>>n>>m;
        int father,num,son;
        for(int i=0;i<m;i++){
            cin>>father>>num;
            for(int j=0;j<num;j++){
                cin>>son;
                nodes[father].push_back(son); // at first i write push_back[]
            }
        }
        level=1;
        dfs(1,level);
        cout<<ans[1];
        for(int i=2;i<=level;i++) //at first i write push_back[] < but not <=
            cout<<' '<<ans[i];
            system("pause");
        return 0;
    }
    

    2.2 stack

    找到与最先出发点的所有邻接点,将他们入栈,
    标记这些点已经访问过,后面和bfs的队列实现有点像。
    UVA280
    
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=150;
    int node_num,st,ed,stnodenum,stnode,vis[maxn];
     
    void dfs(int stnode,vector<int> v[]){
        memset(vis,0,sizeof(vis));
        stack<int> s;
        vector<int> t;
        for(int i=0;i<v[stnode].size();i++){
            int temp=v[stnode][i];
            if(!vis[temp]){
                s.push(temp);
                vis[temp]=1;
            }
        }
        while(!s.empty()){
            int ans=s.top();
            s.pop();
            for(int i=0;i<v[ans].size();i++){
                int temp=v[ans][i];
                if(!vis[temp]){
                    s.push(temp);
                    vis[temp]=1;
                }
            }
        }
        for(int i=1;i<=node_num;i++){
            if(!vis[i])
            t.push_back(i);
        }
        cout<<t.size();
        for(int i=0;i<t.size();i++)
            cout<<" "<<t[i];
        cout<<endl;
    }
     
    int main(){
        while(scanf("%d",&node_num)!=EOF){
            if(node_num==0) break;
            vector<int> v[maxn];
            for(;;){
                scanf("%d",&st);
                if(!st)
                    break;
                for(;;){
                    scanf("%d",&ed);
                    if(!ed)
                        break;
                    v[st].push_back(ed);
                }
            }
            scanf("%d",&stnodenum);
            for(int i=0;i<stnodenum;i++){
                scanf("%d",&stnode);
                dfs(stnode,v);
            }
        }
        return 0;
    

    3. BFS

    3.1 QUEUE

    PAT 1004
    #include<iostream>
    #include<queue>
    #include<vector>
    
    using namespace std;
    vector<int>nodes[100];
    int ans[105];
    int depth[105];
    int level;
    void bfs(int id){
        queue<int>q;
        q.push(id);
        while(!q.empty()){
            int temp=q.front(); //at first i write "top()"
            q.pop();
            level=max(level,depth[temp]);
            if(nodes[temp].size()==0){
                ans[depth[temp]]++;
            }
            else{
                for(int i=0;i<nodes[temp].size();i++){
                    depth[nodes[temp][i]]=depth[temp]+1;
                    q.push(nodes[temp][i]);
                }
            }
            
        }
    }
    
    int main(){
        int n,m;
        cin>>n>>m;
        int father,num,son;
        for(int i=0;i<m;i++){
            cin>>father>>num;
            for(int j=0;j<num;j++){
                cin>>son;
                nodes[father].push_back(son); // at first i write push_back[]
            }
        }
        depth[1]=1;
        level=1;
        bfs(1);
        cout<<ans[1];
        for(int i=2;i<=level;i++) //at first i write push_back[] < but not <=
            cout<<' '<<ans[i];
            system("pause");
        return 0;
    }
    

    3.2 recursion

    void BFS(int st) {
    	int len = G[st].size();
    	for (int i = 0 ; i < len ; i ++ ) {
    		que.push(G[st][i]);
    	}
    	if ( !que.empty() ) {
    		int top = que.front() ; que.pop() ;
    		printf("%d ",top) ;
    		BFS(top) ;
    	}
    

    4. topo 拓扑排序

    //拓扑排序可以判断有向图有没有环。
    //dfs判断图联通。

    5. math

    5.1 euler path /circuit

    https://www.cnblogs.com/wkfvawl/p/9626163.html

    DFS Fleury(佛罗莱)算法求解

    5.2 Huffman Coding 哈夫曼编码

    6. GRAPH 图

    6.1 Red Black Tree

    6.2 AVL

    6.3 tree traversal 树的遍历

    https://www.cnblogs.com/qjmnong/p/9135386.html

    Pre-order

    recursive

    void pre_order(TreeNode * Node)
    {
    if(Node == NULL)
    return;
    printf("%d ", Node->data);
    pre_order(Node->left);
    pre_order(Node->right);
    }

    Iteration

    class TreeNode {
    	public int val;
    	public TreeNode left, right;
    
    	public TreeNode(int val) {
    		this.val = val;
    		this.left = this.right = null;
    	}
    }
    

    先push(root)
    node = pop()
    loop:
    list.add( node.val )
    push( node.right )
    push( node.left )
    循环步骤直到栈空

    public List<Integer> preorderTraversal(TreeNode root) {
    		if (root == null) {
    			return null;
    		}
    		List<Integer> list = new ArrayList<Integer>();
    
    		Stack<TreeNode> s = new Stack<TreeNode>();
    		s.push(root);
    
    		while (!s.isEmpty()) {
    			
    			TreeNode node = s.pop();
    			list.add(node.val);
    			
    			if (node.right != null) {
    				s.push(node.right);
    			}
    			
    			if (node.left != null) {
    				s.push(node.left);
    			}
    		}
    		
    		return list;
    	}
    

    Middle-order

    recursive

    void middle_order(TreeNode *Node)//中序遍历递归算法
    {
        if(Node == NULL)
            return;
        middle_order(Node->left);
        printf("%d ", Node->data);//在中间
        middle_order(Node->right);
    }
    

    Iteration

    把root、以及root左孩子都压入栈中
    loop:
    node = pop()
    list.add( node.val )
    root = node.right
    循环步骤直到栈为空且root为null

    public static List<Integer> inorderTraversal(TreeNode root) {
    		if (root == null) {
    			return null;
    		}
    		List<Integer> list = new ArrayList<Integer>();
    
    		Stack<TreeNode> s = new Stack<TreeNode>();
    
    		do {
    			while (root != null) {
    				s.push(root);
    				root = root.left;
    			}
    			if (!s.isEmpty()) {
    				TreeNode node = s.pop();
    				list.add(node.val);
    				root = node.right;
    			}
    		} while (!s.isEmpty() || root != null);
    
    		return list;
    	}
    

    Post-order

    recursive

    void post_order(TreeNode *Node)//后序遍历递归算法
    {
        if(Node == NULL)
            return; 
        post_order(Node->left);
        post_order(Node->right);
        printf("%d ", Node->data);//在最后
    }
    

    Iteration

    先push(root)
    loop:
    node = pop()
    list.add( 0 , node.val )
    push( node.left )
    push( node.right )
    循环步骤3直到栈空
    之后倒序遍历list

    public static List<Integer> postorderTraversal(TreeNode root) {
    		if (root == null) {
    			return null;
    		}
    		List<Integer> list = new ArrayList<Integer>();
    
    		Stack<TreeNode> s = new Stack<TreeNode>();
    		
    		s.push(root);
    		
    		while( !s.isEmpty() ) {
    			TreeNode node = s.pop();
    			if(node.left != null) {
    				s.push(node.left);
    			}
    			
    			if(node.right != null) {
    				s.push(node.right);
    			}
    			
    			list.add(0, node.val);
    		}
    		
    		return list;
    	}
    

    6.4 BST (binary search tree)

    https://www.cnblogs.com/lqerio/p/11901828.html

    6.5 最短路

    https://blog.csdn.net/strve/article/details/80957491
    Floyed +Dijkstra + Bellman-Ford + SPFA (SPFA就是队列优化版的BF)。
    ///BF 适用于含有负边的图。如果有负边,返回false。Dijkstra算法无法判断含负权边的图的最短路.二者都适用于有向有环图。
    //拓扑排序可以判断有向图有没有环。
    //dfs判断图联通。

    6.5.1 dijkstra

    PAT 1003 为例

    模板 Dijkstra+链式前向星+堆优化

    https://www.cnblogs.com/zmin/p/7349100.html

    matrix O() 邻接矩阵版

    #include<bits/stdc++.h>
    using namespace std;
    int graph[505][505];//图
    int city[505],dis[505],pathNum[505],teamNum[505];//每个城市救护队的数量、到达每个城市的最短距离、到达每个城市的最短路径的数量、到达每个城市的救护队数量
    bool visit[505];//每个城市是否被访问过
    int N,M,C1,C2;
    void Dijkstra(){
        while(!visit[C2]){//如果终点城市还没有被访问,继续循环
            int MIN=INT_MAX,v=-1;//找出目前距离最短的还没有被访问的城市
            for(int i=0;i<N;++i)
                if(!visit[i]&&MIN>dis[i]){
                    MIN=dis[i];
                    v=i;
                }
            visit[v]=true;//标记为已访问
            for(int i=0;i<N;++i)
                if(!visit[i]&&graph[v][i]!=0&&dis[v]+graph[v][i]<dis[i]){
                    dis[i]=dis[v]+graph[v][i];//更新最短路径长度
                    pathNum[i]=pathNum[v];//更新最短路径数量
                    teamNum[i]=teamNum[v]+city[i];//更新城市的救护队数量
                }else if(graph[v][i]!=0&&dis[v]+graph[v][i]==dis[i]){
                    pathNum[i]+=pathNum[v];//增加最短路径数量
                    teamNum[i]=max(teamNum[i],teamNum[v]+city[i]);//找出能够召集最多的城市救护队数量
                }
        }
    }
    int main(){
        scanf("%d%d%d%d",&N,&M,&C1,&C2);
        for(int i=0;i<N;++i)
            scanf("%d",&city[i]);
        while(M--){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            graph[a][b]=c;
            graph[b][a]=c;
        }
        fill(dis,dis+N,INT_MAX);//将最短路径均设置为最大值
        dis[C1]=0;//C1城市是起点,最短路径为0
        teamNum[C1]=city[C1];//C1城市是起点,最短路径数量为1
        pathNum[C1]=1;//C1城市是起点,能够召集的救护队数量为本城市的数量
        Dijkstra();
        printf("%d %d",pathNum[C2],teamNum[C2]);//输出
        return 0;
    }
    

    邻接表版

    #include<bits/stdc++.h>
    using namespace std;
    struct Road{
        int v;//道路尽头的城市编号
        int length;//道路长度
        Road(int vv=0,int l=0):v(vv),length(l){}
    };
    vector<vector<Road>>graph(505);//图
    int city[505],dis[505],pathNum[505],teamNum[505];//每个城市救护队的数量、到达每个城市的最短距离、到达每个城市的最短路径的数量、到达每个城市的救护队数量
    bool visit[505];//每个城市是否被访问过
    int N,M,C1,C2;
    void Dijkstra(){
        while(!visit[C2]){//如果终点城市还没有被访问,继续循环
            int MIN=INT_MAX,v=-1;//找出目前距离最短的还没有被访问的城市
            for(int i=0;i<N;++i)
                if(!visit[i]&&dis[i]<MIN){
                    MIN=dis[i];
                    v=i;
                }
            visit[v]=true;//标记为已访问
            for(Road r:graph[v]){
                if(!visit[r.v]&&dis[r.v]>dis[v]+r.length){
                    dis[r.v]=dis[v]+r.length;//更新最短路径长度
                    pathNum[r.v]=pathNum[v];//更新最短路径数量
                    teamNum[r.v]=teamNum[v]+city[r.v];//更新城市的救护队数量
                }else if(dis[r.v]==dis[v]+r.length){
                    pathNum[r.v]+=pathNum[v];//增加最短路径数量
                    teamNum[r.v]=max(teamNum[r.v],teamNum[v]+city[r.v]);//找出能够召集最多的城市救护队数量
                }
            }
        }
    }
    int main(){
        scanf("%d%d%d%d",&N,&M,&C1,&C2);
        for(int i=0;i<N;++i)
            scanf("%d",&city[i]);
        while(M--){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            graph[a].push_back(Road(b,c));
            graph[b].push_back(Road(a,c));
        }
        fill(dis,dis+N,INT_MAX);//将最短路径均设置为最大值
        dis[C1]=0;//C1城市是起点,最短路径为0
        pathNum[C1]=1;//C1城市是起点,最短路径数量为1
        teamNum[C1]=city[C1];//C1城市是起点,能够召集的救护队数量为本城市的数量
        Dijkstra();
        printf("%d %d",pathNum[C2],teamNum[C2]);//输出
        return 0;
    }
    

    priority_queue lrj版

    设m edges,n vertexs
    复杂度 mlog(n)
    算法中 ** while(!Q.empty()){} ** 部分使得每个边都被遍历到,m。而优先队列插入复杂度为log(n).故整体mlog(n)
    注意m可能大于n^2 最后复杂的>n^2.但不常见

    PAT 1003
    
    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include<vector>
    
    using namespace std;
    const int maxn = 505 + 5; //vertexs
    const int INF = 99999999;
    
    int city[505];
    int pathnum[505],teamnum[505];
    
    struct Edge
    {
        int from,to,dist;
        Edge(int f=0,int t=0,int d=0):from(f),to(t),dist(d){}
    };
    struct HeapNode//优先队列节点
    {
        int d,u;
        HeapNode(int _d=0,int _u=0):d(_d),u(_u){}
        bool operator<(const HeapNode &rhs)const
        {
            return d>rhs.d;
        }
    };
    struct Dijkstra  //边权为正 负权存在用Bellman-Ford 每两点间最短路floyd
    {
        int n,m;               //点数和边数  O(mlog n)
        vector<Edge> edges;    //边列表
        vector<int> G[maxn];   //每个节点出发的边编号(编号从0开始)
        bool done[maxn];       //是否已永久标号
        int d[maxn];           //s到各个点的距离
        int p[maxn];           //最短路中的上一条边
        void init(int n)
        {
            this->n=n;
            for(int i=0;i<n;i++)G[i].clear();
            edges.clear();
        }
        void AddEdge(int from,int to,int dist)
        {
            edges.push_back(Edge(from,to,dist));
            m=edges.size();
            G[from].push_back(m-1);
            
                    edges.push_back(Edge(to,from,dist)); //无向图,双向
            m=edges.size();
            G[to].push_back(m-1);
        }
    
        void dijkstra(int s)   //s start
        {
            priority_queue<HeapNode> Q;   //优先队列,d[i]越小越先出队
            for(int i=0;i<n;i++)d[i]=INF;
            d[s]=0;
            memset(done,0,sizeof(done));
            Q.push(HeapNode(0,s));
            while(!Q.empty()) //第一轮将s能到的点都压入队列,之后每次取d[i]最小的点先出(优先队列)
            {
                HeapNode x=Q.top();Q.pop();
                int u=x.u;                     //u 当前处理点编号
                if(done[u])continue;
                done[u]=true;
                for(int i=0;i<G[u].size();i++)
                {
                    Edge &e=edges[G[u][i]];
                    if(d[e.to]>d[u]+e.dist)
                    {
                        d[e.to]=d[u]+e.dist; //d[u],出发点s到u的距离
                        p[e.to]=G[u][i];     //到达e.to点的边为G[u][i]
                        Q.push(HeapNode(d[e.to],e.to));
                            pathnum[e.to]=pathnum[e.from];
                            teamnum[e.to]=city[e.to]+teamnum[e.from];
                    }
                    else if(d[e.to]==d[u]+e.dist){
                             pathnum[e.to]+=pathnum[e.from];
                            teamnum[e.to]=max(city[e.to]+teamnum[e.from],teamnum[e.to]);
                    }
                }
            }
        }
    };
    
    int main()
    {
        Dijkstra dijk;
        int n,m,start,end;                 //n number of vertex m number of edges
        cin>>n>>m>>start>>end;
        for(int i=0;i<n;i++)
            cin>>city[i];
            dijk.init(n);
            int from,to,dist;
            for(int i = 0; i < m; i++) {
                scanf("%d%d%d",&from,&to,&dist);
                dijk.AddEdge(from,to,dist);
            }
        pathnum[start]=1;
        teamnum[start]=city[start];
        dijk.dijkstra(start);
        cout<<pathnum[end]<<' '<<teamnum[end];
        
        return 0;
    }
    
    

    6.5.2 SPFA

    woj1009

    // woj1009
    
    #define INF 0x3f3f3f3f
    
    
    char word[4005];
    int plovers,slovers;
    int n, m,edgenum;
    const int maxn=105;  //const    点的数
    
    struct Edge {
    int from, to, power,speed,dist;
    char word;
    Edge(int u, int v,int p,int s, int d,char word):from(u),to(v),power(p),speed(s),dist(d),word(word){}
    };
    
    vector<Edge> edges;
    vector<int> G[maxn];
    bool inq[maxn]; //是否在队列里
    int d[maxn]; //s到各个点的距离
    int p[maxn]; //最短路中的上一条弧
    int cnt[maxn]; //入队次数 次数大于n则说明有负环
    
    void init(int n) {
    edgenum=0;
    for(int i = 0; i < n; i++) G[i].clear();
    edges.clear();
    }
    
    void AddEdge(int from, int to, int power,int speed,int dist,char word) {
    edges.push_back(Edge(from, to, power,speed,dist,word));
    edgenum = edges.size();           //错误,一开始写成m,而m又是全局变量导致下面data()的循环除了问题
    G[from].push_back(edgenum-1);  //边的标号
    }
    
    //拓扑排序可以判断有向图有没有环
    //dfs判断图联通
    
    bool bellman_ford(int s) {  ///BF 适用于含有负边的图。如果有负边,返回false。Dijkstra算法无法判断含负权边的图的最短路.二者都适用于有向有环图
        queue<int> Q;
        memset(inq, 0, sizeof(inq));
        memset(cnt, 0, sizeof(cnt));
        for(int i = 0; i < n; i++) d[i] = INF;
        d[s] = 0;
        inq[s] = true;
        p[s]=-1;     //加了一条
        Q.push(s);
        while(!Q.empty()) {
            int u = Q.front(); Q.pop();
            inq[u] = false;
            for(int i = 0; i < G[u].size(); i++) {
                Edge& e = edges[G[u][i]];
                    if(d[u] < INF && d[e.to] > d[u] + e.dist&&plovers>e.power&&slovers>e.speed) {    //模板,+条件
                        d[e.to] = d[u] + e.dist;
                        p[e.to] = G[u][i];
                        if(!inq[e.to]) { Q.push(e.to); inq[e.to] = true; if(++cnt[e.to] > n) return false;}
                    }
            }
        }
        vector<char>ans;  //也可以写一个函数递归,没必要
        int tmp=p[n-1];
        while(tmp!=-1){
            ans.push_back(edges[tmp].word);
            tmp=p[edges[tmp].from];
        }
        for(int i=ans.size()-1;i>-1;i--)
            cout<<ans[i];
        cout<<endl;
        return true;
    }
    
    
    void data(){
        init(n);
        int from,to,power,speed,dist,tmp;
        char word;
        for(int i=0;i<m;i++){
            /*  这样写有问题。读了空格
               scanf("%d%d%d%d%d",&from,&to,&power,&speed,&dist);
               scanf("%c",&word);
               */
              /*
              scanf("%d%d%d%d%d",&from,&to,&power,&speed,&dist);
               getchar();scanf("%c",&word);getchar();*/     //处理最后一个字符前的空格这样可以,但是麻烦
               scanf("%d %d %d %d %d %c",&from,&to,&power,&speed,&dist,&word);  //注意%c不是%s 。也可以fstream
               AddEdge(from,to,power,speed,dist,word);
               }
        cin>>plovers>>slovers;
        bellman_ford(0);
    }
    
    
    

    6.6 生成树

    6.7 如何建图?

    邻接矩阵  //数据范围很大,不能用邻接矩阵
    
    邻接表
    
    邻接表可以用 链表或者 vector 见 woj1006
    
    vector<int>mapp;
    for(int i=0;i<n;i++)
                mapp[i].clear();
            for(int i=0;i<m;i++){
                scanf("%d%d", &x, &y);  mapp[x].push_back(y);  mapp[y].push_back(x);
            }
    
    
    紫书模板建图 见我的题解 woj1009
    
    
    一般的用vector[i]表示i所连边 见我的题解 woj1024
    
    

    7. Sort

    https://www.cnblogs.com/lqerio/p/13484897.html

    8. greedy 贪心

    https://www.cnblogs.com/lqerio/p/11749926.html

    9. 字符串 string

    9.1 KMP

    9.2 AC 自动机

    9.3 字典序 Dictionary order

    https://www.cnblogs.com/lqerio/p/11785894.html

    sort,strcmp,string

    woj1013
    字典序全排列生成:https://www.cnblogs.com/lqerio/p/12079873.html
    
    比较可以用sort(qsort不推荐)
    bool cmp(char*a,char*b){
        return strcmp(a,b);
    }
    
    bool cmp1(string a,string b){
        return a<b;
    }
    vector<string>ans;
    sort(ans.begin(),ans.end(),cmp1);
    

    9.4 leetcode5 Manacher法 最长回文字符串

    https://www.cnblogs.com/lqerio/p/11723652.html

    10. 网络流

    见woj1008.

    11. kth biggest/smallest

    https://www.cnblogs.com/lqerio/p/9757284.html

    12. others

    12.1 make an structure of O(1) search,insert,delete

    leetcode381

    12.2 GCD

        int gcd(int a,int b)
        {
           // return (b==0)?gcd(b,a%b):a
             if(b==0)
                  return a;
             else
                  return gcd(b,a%b);
        }
    

    12.3 Prime

    bool isPrime(int n) {
    
    	if (n < 2)
    		return false;
       int m=sqrt(n+0.5);
    	for (int i = 2; i <= m; i++) {
    
    		if (n % i == 0)
    			return false;
    	}
    
    	return true;
    }
    
    void euler_sieve(int n)  //线性筛
    {
        totPrimes = 0;
        memset(flag, 0, sizeof(flag));
    
        for (int i = 2; i <= n; i++) {
            if (!flag[i])
                primes[totPrimes++] = i;
            for (int j = 0; i * primes[j] <= n; j++) {
                flag[i*primes[j]] = true;
                if (i % primes[j] == 0)
                    break;
            }
        }
    }
    
    void eratosthenes_sieve(int n)
    {
        totPrimes = 0;
        memset(flag, 0, sizeof(flag));
    
        int sqrtn = sqrt(n + 0.5);
        for (int i = 2; i <= sqrtn; i++) {
            if (!flag[i]) {
                primes[totPrimes++] = i;
                for (int j = i * i; j <= n; j += i) {
                    flag[j] = true;
                }
            }
        }
        for (int i = sqrtn + 1; i <= n; i++) {
            if (!flag[i])
                primes[++totPrimes] = i;
        }
    }
    
    int binarysearch(int x)
    {
        int l=0,r=n*n;
        while(r-l>=1)
        {
            int i=(r+l)/2;
            if(num[i]==x) return 1;
            else if(num[i]<x) l=i+1;
            else r=i;
        }
        return 0;
    }
    

    12.5 pow

    ll pow(ll a,ll n) //a^n
    {
        ll result=1,flag=a;
        while(n!=0)
        {
            if(n&1)
                result=result*flag;
            flag=flag*flag;
            n=n>>1;
        }
        return result;
    }
    
    ll pow(ll a,ll n,ll b) //a^n %b  to avoid Integer overflow
    {
        ll result=1;
        a=a%b;
        while(n>0)
        {
            if(n%2==1)
                result=result*a%b;
            n=n/2;
            a=a*a%b;
        }
        return result;
    }
    

    12.6 floating numbers

    uva11809
    https://blog.csdn.net/crazysillynerd/article/details/43339157

    
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <cmath>
     
    using namespace std;
     
    int main() {
        double M[20][40];
        long long E[20][40];
     
        // 打表
        for(int i = 0; i <= 9; ++i) for(int j = 1; j <= 30; ++j) {
            double m = 1 - pow(2, -1 - i), e = pow(2, j) - 1;
            double t = log10(m) + e * log10(2);
            E[i][j] = t, M[i][j] = pow(10, t - E[i][j]);
        }
     
        // 输入并输出结果
        string in;
        while(cin >> in && in != "0e0") {
            // 处理输入
            for(string::iterator i = in.begin(); i != in.end(); ++i) if(*i == 'e') *i = ' ';
            istringstream ss(in);
            double A; int B;
            ss >> A >> B;
            while(A < 1) A *= 10, B -= 1;
            // 在打好的表中寻找答案
            for(int i = 0; i <= 9; ++i) for(int j = 1; j <= 30; ++j) {
                if(B == E[i][j] && (fabs(A - M[i][j]) < 1e-4 || fabs(A / 10 - M[i][j]) < 1e-4)) {
                    cout << i << ' ' << j << endl;
                    break;
                }
            }
        }
    }
    

    12.7 high accuracy

    https://www.cnblogs.com/ECJTUACM-873284962/p/6509429.html
    uva 1828 fibonacci
    https://www.xuebuyuan.com/1888279.html

    #include <iostream>
    #include <string.h>
    
    using namespace std;
    
    int f[5010][1010];       //第1个5010用来存5010个斐波那契数(测试可知第5000项已超过了1000位),第2个1010表示给每个斐波那契数开1010位
    
    int main()
    {
        int i, j;
    
        memset(f, 0, sizeof(f));
    
        f[1][0] = 1;        //给第1个斐波那契数置数
        f[2][0] = 1;        //给第2个斐波那契数置数
    
        for(i = 3; i < 5010; i++)      //从第3项开始,用前2项相加
        {
            int C = 0;      //C表示进位,开始设为0
            for(j = 0; j < 1001; j++)
            {
                f[i][j] = (f[i-2][j] + f[i-1][j] + C) % 10;     //%10后就是这一位该有的数字
                C = (f[i-2][j] + f[i-1][j] + C) / 10;       //相加产生的进位
            }
    
        }
    
        int a;
        while(cin>>a)
        {
            for(j = 1001; j >= 0; j--)      //寻找最高位
                if(f[a][j] != 0)
                    break;
            for(; j >= 0; j--)
                cout<<f[a][j];
            cout<<endl;
        }
        return 0;
    }
    

    https://www.cnblogs.com/lqerio/p/11117608.html

    12.9 c++ stl

    https://www.cnblogs.com/lqerio/p/13484897.html
    https://www.cnblogs.com/lqerio/p/11117601.html

    12.10 滑动窗口 Sliding window

    https://www.cnblogs.com/lqerio/p/11708680.html
    https://www.cnblogs.com/lqerio/p/9741044.html

    12.11 双指针...三指针... two-pointer

    https://www.cnblogs.com/lqerio/p/11755868.html

  • 相关阅读:
    explain组合索引是否命中
    高并发优化
    docker基础篇一
    Web API 集成Serilog
    复习一下CSS,做笔记记录一下
    Process调用winform程序
    winform自动更新
    格式化xml 给没有节点的内容添加节点
    2.Grpc消息定义
    1.Grpc环境配置
  • 原文地址:https://www.cnblogs.com/lqerio/p/13535931.html
Copyright © 2011-2022 走看看