1. 程式人生 > 實用技巧 >各類演算法模板

各類演算法模板

gcd

輾轉相除法求最大公約數

View Code

或者

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); }
View Code


那麼求什麼最大公約數最小公倍數 乘法逆元全都解決了

當然我當時也費盡心思研究了一番 為了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;
}

快速冪演算法:

#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;
}
 

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

最短路徑(暴力)

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];
            }
        }
    } 

尤拉篩篩素數

#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;
}

讀入優化

#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