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);
    

      

      

  • 相关阅读:
    Java语言中:float数据类型在内存中是怎么存储的?
    Java语言中:在数据类型的讲解中补充的几个小问题
    groovy : poi 导出 Excel
    php 基础入门篇之前言
    C 实现strcmp,strcpy,strcat函数
    CSDN 夏令营程序 试题分析 (3)
    HDU 1560 IDA*搜索
    iOS怎样找到自己的沙盒
    51系列小型操作系统精髓 简单实现2
    排序算法总结之折半插入排序
  • 原文地址:https://www.cnblogs.com/ZhaoxiCheung/p/5850145.html
Copyright © 2011-2022 走看看