各类算法模板

gcd

 

int gcd(int a,int b)///辗转相除法求最大公约数
{

    int t = a;
    while(a%b)
    {
        a=b;
        b=t%b;
        t=a;
    }
    return b;
}
View Code

或者

int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a%b);
}
View Code

exgcd

扩展欧几里得算法

给予二整数 a 与 b, 必存在有整数 x 与 y 使得ax + by = gcd(a,b)

int exgcd(int a2,int  b2,int &x,int &y)
{
    if(b2==0)
    {
        x=1;y=0;
        return a2;
    }

    int ans = exgcd(b2,a2%b2,x,y);
    double temp=x;
    x=y;
    y=temp-a2/b2*y;
    return ans;       ///返回的还是最大公约数 但是我们就方便求x和y

}
View Code
int tocal(int a3,int b3)
{
    int x0,y0;
    int gcd = exgcd(a3,b3,x0,y0);
    if(1%gcd!=0) return -1; ///gcd得等于1  ...
    x0*=1/gcd;
    b3=abs(b3);
    int ans = x0%b3;
    if (ans<=0) ans+=b3;
    return ans;


}
View Code

lcm:

 

int lcm(int a,int b)
{
    return a * b / gcd(a, b);
}

 

那么求什么最大公约数最小公倍数 乘法逆元全都解决了

当然我当时也费尽心思研究了一番 为了RSA加密算法

 

 

01背包:

 

有一个容量为V的背包,现在有n件物品,每件物品所占空间为w[i],价值为v[i],求 背包中所装物品价值最大值

注意每个物品就一件

 

for(i=1;i<=n;i++)
    for(j=V;j>=w[i];j--)
        f[j]=max(f[j],f[j-w[i]]+v[i]);

 

完全背包

完全背包是有n种物品,每种物品可以取无线多件,每件物品所占空间为w[i],价值为v[i]

 

for(i=1;i<=n;i++)
    for(j=w[i];j<=V;j++)
        f[j]=max(f[j],f[j-w[i]]+v[i]);

高精度加法:

 

#include<bits/stdc++.h>
using namespace std;
string a,b;
string Precise_add(string a,string b){
    int lena=a.length();
    int lenb=b.length();
    int aa,bb,sum,flag=0;
    while(lena>0){
        aa=a[lena-1]-'0';
        if(lenb>0)
            bb=b[lenb-1]-'0';
        else
            bb=0;
        sum=aa+bb+flag;
        if(sum>=10){
            a[lena-1]='0'+sum%10;
            flag=1;
        } 
        else{
            a[lena-1]='0'+sum;
            flag=0;
        }
        lena--;
        lenb--;
    } 
    if(flag==1)
        a="1"+a;
    return a;
}
int main(){
    cin>>a>>b;
    if(a.size()<b.size())
        swap(a,b);
    cout<<Precise_add(a,b)<<endl;
    return 0;
}
View Code

快速幂算法:

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll Q(ll n,ll m){
    ll res=1;
    while(m){
        if(1&m)
            res=res*n;
        n=n*n;
        m>>=1;
    }
    return res;
}
int main(){
    
    cout<<Q(5,12)<<endl;
    return 0;
}
View Code

DFS:

 

#include<bits/stdc++.h>
using namespace std;
int a[105][105],b[105][105];
int n,m,startx,starty,endx,endy,ans=999999999;
int next[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
void dfs(int x,int y,int step){
    if(x==endx&&y==endy){
        ans=min(ans,step);
        return;
    }
    for(int i=0;i<4;i++){
        int xx=x+next[i][0];
        int yy=y+next[i][1];
        if(xx<1||xx>n||yy<1||yy>m) continue;
        if(a[xx][yy]==0&&b[xx][yy]==0){
            b[xx][yy]=1;
            dfs(xx,yy,step+1);
            b[xx][yy]=0;
        }
    }
    return;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>a[i][j]; 
    cin>>startx>>starty>>endx>>endy;
    dfs(startx,starty,0);
    cout<<ans;
    return 0;
}
View Code

最短路径 暴力

 

for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(e[i][j]>e[i][k]+e[k][j])
                    e[i][j]=e[i][k]+e[k][j];
            }
        }
    }
View Code

底杰斯特拉算法

#include<bits/stdc++.h>

#define MAX         100                 // 矩阵最大容量

 #define INF         (~(0x1<<31))        // 最大值(即0X7FFFFFFF)
 #define LENGTH(a)   (sizeof(a)/sizeof(a[0]))
 // 邻接矩阵
 typedef struct _graph
 {
     char vexs[MAX];       // 顶点集合
     int vexnum;           // 顶点数
     int edgnum;           // 边数
     int matrix[MAX][MAX]; // 邻接矩阵
 }Graph, *PGraph;
 

 Graph* create_example_graph()
 {
     char vexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
     int matrix[][9] = {
              /*A*//*B*//*C*//*D*//*E*//*F*//*G*/
       /*A*/ {   0,  12, INF, INF, INF,  16,  14},
       /*B*/ {  12,   0,  10, INF, INF,   7, INF},
       /*C*/ { INF,  10,   0,   3,   5,   6, INF},
       /*D*/ { INF, INF,   3,   0,   4, INF, INF},
       /*E*/ { INF, INF,   5,   4,   0,   2,   8},
       /*F*/ {  16,   7,   6, INF,   2,   0,   9},
       /*G*/ {  14, INF, INF, INF,   8,   9,   0}};
     int vlen = LENGTH(vexs);
     int i, j;
     Graph* pG;
     
     // 输入"顶点数"和"边数"
     if ((pG=(Graph*)malloc(sizeof(Graph))) == NULL )
         return NULL;
     memset(pG, 0, sizeof(Graph));
 
     // 初始化"顶点数"
     pG->vexnum = vlen;
     // 初始化"顶点"
     for (i = 0; i < pG->vexnum; i++)
         pG->vexs[i] = vexs[i];
 
     // 初始化"边"
     for (i = 0; i < pG->vexnum; i++)
         for (j = 0; j < pG->vexnum; j++)
             pG->matrix[i][j] = matrix[i][j];
 
     // 统计边的数目
     for (i = 0; i < pG->vexnum; i++)
         for (j = 0; j < pG->vexnum; j++)
             if (i!=j && pG->matrix[i][j]!=INF)
                 pG->edgnum++;
     pG->edgnum /= 2;
 
     return pG;
 }
 
 
 
 
 
 


 void dijkstra(Graph G, int vs, int prev[], int dist[])
 {
     int i,j,k;
     int min;
     int tmp;
     int flag[MAX];      // flag[i]=1表示"顶点vs"到"顶点i"的最短路径已成功获取。
     
     // 初始化
     for (i = 0; i < G.vexnum; i++)
     {
         flag[i] = 0;              // 顶点i的最短路径还没获取到。
         prev[i] = 0;              // 顶点i的前驱顶点为0。
         dist[i] = G.matrix[vs][i];// 顶点i的最短路径为"顶点vs"到"顶点i"的权。
     }
 
     // 对"顶点vs"自身进行初始化
     flag[vs] = 1;
     dist[vs] = 0;
 
     // 遍历G.vexnum-1次;每次找出一个顶点的最短路径。
     for (i = 1; i < G.vexnum; i++)
     {
         // 寻找当前最小的路径;
         // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
         min = INF;
         for (j = 0; j < G.vexnum; j++)
         {
             if (flag[j]==0 && dist[j]<min)
             {
                 min = dist[j];
                 k = j;
             }
         }
         // 标记"顶点k"为已经获取到最短路径
         flag[k] = 1;
 
         // 修正当前最短路径和前驱顶点
         // 即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
         for (j = 0; j < G.vexnum; j++)
         {
             tmp = (G.matrix[k][j]==INF ? INF : (min + G.matrix[k][j])); // 防止溢出
             if (flag[j] == 0 && (tmp  < dist[j]) )
             {
                 dist[j] = tmp;
                 prev[j] = k;
             }
         }
     }
 
     // 打印dijkstra最短路径的结果
     printf("dijkstra(%c): \n", G.vexs[vs]);
     for (i = 0; i < G.vexnum; i++)
         printf("  shortest(%c, %c)=%d\n", G.vexs[vs], G.vexs[i], dist[i]);
 }
 
 
 int main()
 {
     int prev[MAX] = {0};
     int dist[MAX] = {0};
     Graph* pG;
     pG = create_example_graph();
     
     dijkstra(*pG, 3, prev, dist);
     return 0;
     
     
 
 }
 
 
 
 
View Code

 

 

 

 

 

 

 

 

 

欧拉筛筛素数

 

 

#include<bits/stdc++.h>
using namespace std;

void get_prime(vector<int> & prime,int upper_bound){ // 传引用
    if(upper_bound < 2)return;
    vector<bool> Is_prime(upper_bound+1,true);
    for(int i = 2; i <= upper_bound; i++){
        if(Is_prime[i])
            prime.push_back(i);
        for(int j = 0; j < prime.size() and i * prime[j] <= upper_bound; j++){
            Is_prime[ i*prime[j] ] = false;
            if(i % prime[j] == 0)break;// 保证了一个数只被筛一次。
        }
    }
}
int main(){
    vector<int> prime;
    get_prime(prime, 1000);
    for(vector<int> :: iterator it = prime.begin(); it not_eq prime.end(); it++)
        cout<<*it<<" ";
    return 0;
}
View Code

读入优化

 

 

#include<bits/stdc++.h>
using namespace std;


int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin>>n;
    cout<<n;
}
View Code

 

#include<stdio.h> 
#include<iostream>
#include<string.h>
const int MAX=4e6;
using namespace std;
int read(){
    char ch=getchar();
    int x=0,f=1;
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int main(){
    int x;
    cout<<read();
    return 0;
}
View Code

 

并查集

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[10000];
int S(int x){
    if(a[x]==x) return x;
    else{
        a[x]=S(a[x]);
        return a[x];
    }
}
void B(int x,int y){
    int xx=S(x);
    int yy=S(y);
    if(xx!=yy)
        a[yy]=xx;
}
int main(){
    int n,sum=0;cin>>n;
    for(int i=1;i<=n;i++)a[i]=i;
    for(int i=1;i<=n;i++){
        int x,y;cin>>x>>y;
        B(x,y);
    }
    for(int i=1;i<=n;i++)
        if(a[i]==i)
            sum++;
    cout<<sum;
    return 0;
}
View Code

阶乘高精度

 

#include<bits/stdc++.h>
using namespace std;
int num[5000];
int gaojing(int num[],int n){
    int len=1;
    num[0]=1;
    for(int i=1;i<=n;i++){
        len=0;
        int p=0;
        int jw=0;
        while(num[p]!=-1){
            num[p]*=i;
            num[p]+=jw;
            jw=0;
            if(num[p]>=10){
                jw=num[p]/10;
                num[p]%=10;
            }
            p++;
            len++;
        }
        if(jw!=0){
            while(jw){
                num[p++]=jw%10;
                jw/=10;
                len++;
            }
        }
    } 
    return len-1;
}
 
int main(){
    int n;
    while(cin>>n){
        memset(num,-1,sizeof(num));
        int len=gaojing(num,n);
        for(len;len>=0;len--){
            cout<<num[len];
        }
        cout<<endl;
    }
    return 0;
}
View Code

sort

字典序

#include<bits/stdc++.h>
using namespace std;
//algorithm
string a[21];
bool cmp(string a,string b){
    return a+b > b+a;

int main(){
    int n;cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)cout<<a[i]<<" ";
    return 0;
} 

sstream 和 atoi

将字符串类型中的最前面数字转换为整数类型

#include<iostream>
#include<sstream>
using namespace std;
int main(){
    int x;string s;
    cin>>s;
    stringstream ss(s);
    ss>>x;
    cout<<x;
    return 0;
}
#include<iostream>
#include<sstream>
#include<cstdlib>
using namespace std;
int main(){
    int x;string s;
    cin>>s;
    x=atoi(s.c_str());
    cout<<x;
    return 0;
}

 

next_permutation()全排列函数

 

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
    string s="1234567";int sum=0;
    do{
        cout<<s<<'\n';
        sum++;
    }while(next_permutation(s.begin(),s.end()));
    cout<<sum<<'\n';
     return 0;
}
 

 

字符串查找函数 直接替代kmp算了

#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
    ////find函数返回类型 size_type
    string s("sbjkji");
    string flag;
    string::size_type position;
    //find 函数 返回jk 在s 中的下标位置
    position = s.find("ji");
    if (position != s.npos)  //如果没找到,返回一个特别的标志c++中用npos表示,我这里npos取值是4294967295,
    {
        printf("position is : %d\n" ,position);
    }
    else
    {
        printf("Not found the flag\n");
    }
    
    position = s.find("good_girl");
    if (position != s.npos) 
    {
        printf("position is : %d\n" ,position);
    }
    else
    {
        printf("Not found the flag\n");
    }
    
     
    
    
}
View Code

 

 

strstr:

#include<bits/stdc++.h>

/*
 *  strstr函数
 *  功能:在串中查找指定字符串的第一次出现
 *  用法:char *strstr(char *strOne, char *strTwo);
 *  据说strstr函数和KMP的算法效率差不多
 */

int main(int argc, const char * argv[])
{
    char strOne[] = "Hope my cold is better";
    char strTwo[] = "cold";
    char *ptr;
    ptr = strstr(strOne, strTwo);
    std::cout << ptr << '\n';
   
    
    //输出  cold is better
    
     return 0;
}

 

 优先队列

 

#include<iostream>
#include <queue>
using namespace std;
int main()
{
    //对于基础类型 默认是大顶堆
    priority_queue<int> a;
    //等同于 priority_queue<int, vector<int>, less<int> > a;

    //      这里一定要有空格,不然成了右移运算符↓↓
    priority_queue<int, vector<int>, greater<int> > c;  //这样就是小顶堆
    priority_queue<string> b;

    for (int i = 0; i < 5; i++)
    {
        a.push(i);
        c.push(i);
    }
    while (!a.empty())
    {
        cout << a.top() << ' ';
        a.pop();
    }
    cout << endl;

    while (!c.empty())
    {
        cout << c.top() << ' ';
        c.pop();
    }
    cout << endl;

    b.push("abc");
    b.push("abcd");
    b.push("cbd");
    while (!b.empty())
    {
        cout << b.top() << ' ';
        b.pop();
    }
    cout << endl;
    return 0;
    /*
    结果
    4 3 2 1 0
    0 1 2 3 4
    cbd abcd abc
     */ 
    
    
    
    
    
}
View Code

用pair做优先队列元素的例子:

规则:pair的比较,先比较第一个元素,第一个相等比较第二个。

 

#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main()
{
    priority_queue<pair<int, int> > a;
    pair<int, int> b(1, 2);
    pair<int, int> c(1, 3);
    pair<int, int> d(2, 5);
    a.push(d);
    a.push(c);
    a.push(b);
    while (!a.empty())
    {
        cout << a.top().first << ' ' << a.top().second << '\n';
        a.pop();
    }
}
View Code

 

 

 字符串和数字的互相转换:

 

#include<bits/stdc++.h> 
using namespace std;
int main () 
{
  int a;float b;long c;
  string d,e,f; // char d[10],e[10],f[10];

  /* string to number */
  stringstream ss;
  ss << "32";
  ss >> a;
  ss.clear();

  ss << "3.1415";
  ss >> b;
  ss.clear();

  ss << "567283";
  ss >> c;
  ss.clear();

  cout<<a<<","<<b<<","<<c<<endl;

  /* number to string */
  ss << a;
  ss >> d;
  ss.clear();

  ss << b;
  ss >> e;
  ss.clear();

  ss << c;
  ss >> f;
  ss.clear();

  cout<<d<<","<<e<<","<<f<<endl;

  return 0;
}
View Code

bitset

 

#include <iostream>
#include <bitset>

using namespace std;

const int MAXN = 32;

bitset<MAXN> bt(11);

int main()
{
    cout << bt << '\n'; // 输出   0000 ....1011 32位 
    
    cout <<bt.count() << '\n';  //3个1输出3
    
    cout << bt.size()  << '\n'; 
    /*
    bt.flip()       //  把 bt 中所有二进制位逐位取反
    bt.flip(pos)    //  把 bt 中在 pos 处的二进制位取反 
    bt[pos].flip()  //  同上
    bt.set()        //  把 bt 中所有二进制位都置为 1
    bt.set(pos)     //  把 bt 中在 pos 处的二进制位置为 1
    bt.reset()      //  把 bt 中所有二进制位都置为 0
    bt.reset(pos)   //  把 bt 中在pos处的二进制位置为0
    ~ | ^ & 都可以用 

    
    
    
    return 0;
}

 

 

 

 各种进制转换:https://blog.csdn.net/vir_lee/article/details/80645066

 

 

 

记忆化搜索:

https://blog.csdn.net/p2718756941/article/details/95473857

#include <bits/stdc++.h>
using namespace std;
int read()
{
    int x=0,f=1;
    char ch=getchar();//getchar()读入单个字符(包括空格 ,换行符)
    while(ch<'0'||ch>'9'){//非数字(字符)
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);//原二进制数向左平移x位,右边原位置以0补齐(位运算)
        ch=getchar();
    }
    return x*f;
}//快读
 
 
int n,m;
int a[1010][1010];
int dp[1010][1010];
int ans;
 
void CIN()
{
    n=read();
    m=read();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            a[i][j]=read();
            dp[i][j]=1;
        } 
    }
    return;
}
 
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
 
bool in(int x,int y)
{
    if(x>0&&y>0&&x<=n&&y<=m)return 1;
    return 0;
}
 
int DFS(int x,int y){
    if(dp[x][y]>1)return dp[x][y];
    for(int i=0;i<4;i++)
    {
        int xx=x+dir[i][0];
        int yy=y+dir[i][1];
        if(in(xx,yy)&&a[x][y]>a[xx][yy])
            dp[x][y]=max(dp[x][y],DFS(xx,yy)+1);
    }
 
     
    return dp[x][y];
}
 
int main(){
    CIN();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            ans=max(ans,DFS(i,j));
    cout<<ans<<endl;
     
     
    return 0;
}
View Code

 

 

 

埃及分数

https://www.jianshu.com/p/da04c77e11d0

 

import java.io.BufferedReader;
import java.io.InputStreamReader;

//埃及分数
public class EgyptFraction {
    public static void main(String[] args) throws Exception{
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("输入分子");
        int a = Integer.parseInt(bufferedReader.readLine());
        System.out.println("输入分母");
        int b = Integer.parseInt(bufferedReader.readLine());   //输入ab

        int e;

        //要求是如果分子大于1就可以拆分
        do {
           e = b/a + 1;
           System.out.println("1/"+e);

           a = a * e - b;
           b = b * e;

           int maxDiv = maxComDiv(a,b);
           if(maxDiv > 1){
               a /= maxDiv;
               b /= maxDiv;
           }
        }while (a > 1);

        System.out.println("1/"+b);
    }

    private static int maxComDiv(int a, int b) {
        int temp = 0;
        while(b != 0){
            temp = a % b;
            a = b;
            b = temp;
        }
        return a;
    }
}
View Code

 

 

 十进制转26进制

 

#include <bits/stdc++.h>
using namespace std;

char str[27] = {0,'A','B','C','D','E','F','G','H','I','J','K'
               ,'L','M','N','O','P','Q','R','S','T','U','V',
               'W','X','Y','Z'};

int main() {
   int num;
   string ans = "";
   scanf("%d", &num);
   while(num) {
       ans += str[num % 26];
       num /= 26;
   }
   for (int i = ans.size() - 1; i >= 0; i--) {
       cout << ans[i];
   }
   return 0;
}
View Code

 

 

 

数据类型取值范围

 

 

 

 快速读入:

int read(){
    int x=0,f=1;
    char ch=getchar();//getchar()读入单个字符(包括空格 ,换行符)
    while(ch<'0'||ch>'9'){//非数字(字符)
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);//原二进制数向左平移x位,右边原位置以0补齐(位运算)
        ch=getchar();
    }
    return x*f;
}
View Code

 

 

 

 

 

 

解决爆栈 手动加栈:

#pragma comment(linker, “/STACK:1024000000,1024000000”)

 

posted @ 2020-10-07 20:41  然终酒肆  阅读(236)  评论(0编辑  收藏  举报