zoukankan      html  css  js  c++  java
  • 常用模板

    • 1、辗转相除法求最大公约数
    int gcd(int a,int b)
    {
        return b == 0?a:gcd(b,a%b);
    }
    • 2、最大公约数
    int lcm(int a,int b)
    {
        return a/gcd(a,b)*b; //先除后乘防止a*b溢出
    }
    • 3、拓展欧几里德算法
    void extgcd(__int64 a,__int64 b,__int64 &x,__int64 &y)
    {
        if (!b)
        {
            x = 1;
            y = 0;
        }
        else
        {
            extgcd(b,a%b,y,x);
            y -= x*(a/b);
        }
    }
    • 4、求区间[m,n]内的素数( 埃氏筛选法)
    int m = sqrt(n+0.5);
    memset(vis,0,sizeof(vis));
    for (int i = 2; i <= m; i++)
    {
        if (!vis[i])
        {
            for (int j = i*i; j <= n; j += i)
            {
                vis[j] = 1;
            }
        }
    }
    
    版本二O(nloglogn)
    int p = 0;
    memset(is_prime,true,sizeof(is_prime));
    is_prime[0] = is_prime[1] = false;
    for(int i = 2; i <= MAX; i++)
    {
        if (is_prime[i])
        {
            prime[p++] = i;
            for (int j = 2 * i; j <= MAX; j += i)
            {
                is_prime[j] = false;
            }
        }
    }
    • 5、无平方因子的数
    对于不超过√m 的所有素数p,筛选区间[n,m]内p² 的所有倍数
    
    • 6、快速乘
    LL mod_multi(LL x,LL y,LL mod)   //拆分成y个x相加
    {
        LL res = 0;
        while (y)
        {
            if (y&1)
            {
                res += x;
                while (res >= mod)  res -= mod;   
            }
            x += x;
            while (x >= mod)    x -= mod; 
            y >>= 1;
        }
        return res;
    }
    • 7、快速幂
    LL mod_pow(LL x,LL n,LL mod)
    {
        LL res = 1;
        while (n > 0)
        {
            if (n&1)
            {
                res = mod_mulit(res,x,mod);
                // res = res*x%mod;
            }
            x = mod_multi(x,x,mod);
            //x = x*x%mod;
            n >>= 1;
        }
        return res;
    }
    
    • 8、二分查找
    // binsearch_min 返回key(可能有重复)第一次出现的下标,如无return -1
    
    int binsearch_min(int * arr, int lef, int rig, int key)
    {
        if(!arr)    return -1;
        int left = lef, right = rig;
        while(left < right)
        {
            int mid = left + ((right-left)>>1);
            if(arr[mid] < key)
            {
                left = mid+1;
            }
            else
            {
                right = mid;
            }
        }
        if(arr[left] == key)    return left;
        return -1;
    }
    
    // binsearch_max 返回key(可能有重复)最后一次出现的下标,如无return -1
    int binsearch_max(int * arr, int lef, int rig, int key)
    {
        if(!arr)    return -1;
        int left = lef, right = rig;
        while(left < right -1)
        {
            int mid = left + ((right-left)>>1);
            if(arr[mid] <= key)
            {
                left = mid;
            }
            else
            {
                right = mid;
            }
        }
        if(arr[right] == key) // 找max,先判断right
        {
            return right;
        }
        else if(arr[left] == key)
        {
            return left;
        }
        else
            return -1;
    }
    
    • 9、并查集
    void init()
    {
        memset(father,0,sizeof(father));
        memset(rk,0,sizeof(rk));
        for (int i = 0; i <= N; i++)
        {
            father[i] = i;
        }
    }
    
    int find(int x)
    {
        int r = x;
        while (father[r] != r)
        {
            r = father[r];
        }
        int i = x,j;
        while (i != r)           //路径压缩
        {
            j = father[i];
            father[i] = r;
            i = j;
        }
        return r;
    }
    /*
    int find(int x)
    {
        return father[x] == x?father[x]:father[x] = find(father[x]);
    }
    */
    
    void unite(int x,int y)
    {
        int fx,fy;
        fx = find(x);
        fy = find(y);
        if (fx == fy)   return;
        if (rk[fx] < rk[fy])
        {
            father[fx] = fy;
        }
        else
        {
            father[fy] = fx;
            if (rk[fx] == rk[fy])
            {
                rk[fx]++;
            }
        }
    }
    
    • 10、生成1~n的排列
    void permutation(int n,int *A,int cur)
    {
    	if (cur == n)                   //递归边界 
    	{
    		for (int i = 0;i < n;i++)	printf("%d ",A[i]);
    		printf("
    ");
    	}
    	else for (int i = 1;i <= n;i++) //尝试在A[cur}中填各种整数i 
    	{
    		int ok = 1;
    		for (int j = 0;j < cur;j++)	if (A[j] == i)	ok = 0;   //如果i已经在A[0]~A[cur-1]出现过,则不能再选 
    		if (ok)
    		{
    			A[cur] = i;
    			permutation(n,A,cur+1); //递归调用 
    		}
    	}
    }
    
    • 11、生成可重集的排列
    void permutation(int n,int *P,int *A,int cur) //输入数组P,并按字典序输出数组A各元素的所有全排列
    {
        if (cur == n)
        {
            for (int i = 0; i < n; i++)	printf("%d ",A[i]);
            printf("
    ");
        }
        else for (int i = 0; i < n; i++)
        {
            if (!i || P[i] != P[i-1])
            {
                int c1 = 0,c2 = 0;
                for (int j = 0; j < cur; j++)	if (A[j] == P[i])	c1++;
                for (int j = 0; j < n; j++)	if (P[i] == P[j])	c2++;
                if (c1 < c2)
                {
                    A[cur] = P[i];
                    permutation(n,P,A,cur+1);
                }
            }
        }
    }
    
    • 12、强连通分量的targin算法
    /* 寻找有向图强连通分量的tarjan算法
     * index表示的就是时间戳
     * scc_cnt 表示强连通分量的个数
     * belong[u] 表示结点u属于哪一个强连通分量
     * inst[u] 表示结点u是否仍然在栈中
     * st[] 和 top 分别表示栈和栈顶位置
     *index = scc_cnt = top = 0*/
    void targin(int u)
    {
        int v;
        dfn[u] = low[u] = ++index;
        st[++top] = u;
        inst[u] = 1;
        for (int i = head[u];i != -1;i = edge[i].next)
        {
            v = edge[i].v;
            if (!dfn[v])
            {
                targin(v);
                low[u] = min(low[u],low[v]);
            }
            else if (inst[v])
                low[u] = min(low[u],dfn[v]);
        }
        if (low[u] == dfn[u])
        {
            scc_cnt++;
            do
            {
                v = st[top--];
                inst[v] = 0;
                belong[v] = scc_cnt;
            }
            while (u != v);
        }
    }
    
    • 13、SBT
    /*
    * tree[x].left   表示以 x 为节点的左儿子
    * tree[x].right  表示以 x 为节点的右儿子
    * tree[x].size   表示以 x 为根的节点的个数(大小)
    */
     
     
    struct SBT
    {
        int key,left,right,size;
    } tree[10010];
    int root = 0,top = 0;
     
    void left_rot(int &x)         // 左旋
    {
        int y = tree[x].right;
        if (!y) return;
        tree[x].right = tree[y].left;
        tree[y].left = x;
        tree[y].size = tree[x].size;
        tree[x].size = tree[tree[x].left].size + tree[tree[x].right].size + 1;
        x = y;
    }
     
    void right_rot(int &x)        //右旋
    {
        int y = tree[x].left;
        if (!y) return;
        tree[x].left = tree[y].right;
        tree[y].right = x;
        tree[y].size = tree[x].size;
        tree[x].size = tree[tree[x].left].size + tree[tree[x].right].size + 1;
        x = y;
    }
     
    void maintain(int &x,bool flag)  //维护SBT状态
    {
        if (!x) return;
        if (flag == false)           //左边
        {
            if(tree[tree[tree[x].left].left].size > tree[tree[x].right].size)//左孩子的左孩子大于右孩子
                right_rot(x);
            else if (tree[tree[tree[x].left].right].size > tree[tree[x].right].size) //左孩子的右孩子大于右孩子
            {
                left_rot(tree[x].left);
                right_rot(x);
            }
            else
                return;
        }
        else                       //右边
        {
            if(tree[tree[tree[x].right].right].size > tree[tree[x].left].size)//右孩子的右孩子大于左孩子
                left_rot(x);
            else if(tree[tree[tree[x].right].left].size > tree[tree[x].left].size) //右孩子的左孩子大于左孩子
            {
                right_rot(tree[x].right);
                left_rot(x);
            }
            else
                return;
        }
        maintain(tree[x].left,false);
        maintain(tree[x].right,true);
        maintain(x,true);
        maintain(x,false);
    }
     
    void insert(int &x,int key)  //插入
    {
        if (x == 0)
        {
            x = ++top;
            tree[x].left = 0;
            tree[x].right = 0;
            tree[x].size = 1;
            tree[x].key = key;
        }
        else
        {
            tree[x].size++;
            if(key < tree[x].key)
                insert(tree[x].left,key);
            else
                insert(tree[x].right,key);//相同元素可插右子树
            maintain(x,key >= tree[x].key);
        }
    }
     
    int remove(int &x,int key)  //利用后继删除
    {
        tree[x].size--;
        if(key > tree[x].key)
            remove(tree[x].right,key);
        else  if(key < tree[x].key)
            remove(tree[x].left,key);
        else  if(tree[x].left !=0 && !tree[x].right) //有左子树,无右子树
        {
            int tmp = x;
            x = tree[x].left;
            return tmp;
        }
        else if(!tree[x].left && tree[x].right != 0) //有右子树,无左子树
        {
            int tmp = x;
            x = tree[x].right;
            return tmp;
        }
        else if(!tree[x].left && !tree[x].right)    //无左右子树
        {
            int tmp = x;
            x = 0;
            return tmp;
        }
        else                                      //左右子树都有
        {
            int tmp = tree[x].right;
            while(tree[tmp].left)
                tmp = tree[tmp].left;
            tree[x].key = tree[temp].key;
            remove(tree[x].right,tree[tmp].key);
        }
    }
     
    int getmin(int x)    //求最小值
    {
        while(tree[x].left)
            x = tree[x].left;
        return tree[x].key;
    }
     
    int getmax(int x)    //求最大值
    {
        while(tree[x].right)
            x = tree[x].right;
        return tree[x].key;
    }
     
    int pred(int &x,int y,int key)   //前驱,y初始前驱,从0开始, 最终要的是返回值的key值
    {
        if(x == 0)
            return y;
        if(key > tree[x].key)
            return pred(tree[x].right,x,key);
        else
            return pred(tree[x].left,y,key);
    }
     
    int succ(int &x,int y,int key)   //后继,同上
    {
        if(x == 0)
            return y;
        if(key < tree[x].key)
            return succ(tree[x].left,x,key);
        else
            return succ(tree[x].right,y,key);
    }
     
    int select(int &x,int k)   //查找第k小的数
    {
        int r = tree[tree[x].left].size + 1;
        if(r == k)
            return tree[x].key;
        else if(r < k)
            return select(tree[x].right,k - r);
        else
            return select(tree[x].left,k);
    }
     
    int rank(int &x,int key)   //key排第几
    {
        if(key < tree[x].key)
        {
            return rank(tree[x].left,key);
        }
        else if(key > tree[x].key)
            return rank(tree[x].right,key) + tree[tree[x].left].size + 1;
        else
            return tree[tree[x].left].size + 1;
    }
    
    • 14、关闭同步
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    

      

      

  • 相关阅读:
    POJ 3041 Asteroids 最小点覆盖 == 二分图的最大匹配
    POJ 3083 Children of the Candy Corn bfs和dfs
    POJ 2049 Finding Nemo bfs 建图很难。。
    POJ 2513 Colored Sticks 字典树、并查集、欧拉通路
    POJ 1013 Counterfeit Dollar 集合上的位运算
    POJ 2965 The Pilots Brothers' refrigerator 位运算枚举
    无聊拿socket写的100以内的加法考试。。。
    POJ 1753 Flip Game
    初学socket,c语言写的简单局域网聊天
    汇编语言 复习 第十一章 标志寄存器
  • 原文地址:https://www.cnblogs.com/ZhaoxiCheung/p/5850145.html
Copyright © 2011-2022 走看看