算法模板总结

排序:

1.冒泡排序(什么?你也是冒泡人?):

void bubble_Sort(int* arr, int n) {
    for (int i = 0; i1; ++i)
        for (int j = 0; j1; ++j)
            if (arr[j] > arr[j+1])
                swap(arr[j], arr[j+1]);
}

2.快速排序:

void quickSort(int* arr, int low, int high) {
    if (low >= high)
        return;
    int kase = low;
    for (int i = low; i) 
        if (arr[i] < arr[high])
            swap(arr[kase++], arr[i]);
    swap(arr[kase], arr[high]);
    quickSort(arr, low, kase-1);
    quickSort(arr, kase+1, high);
}

3.归并排序:

void mergeSort(int arr[], int temp[], int low, int high) {
    if (low >= high)
        return;
    int len = high-low, mid = len/2 + low;
    int start1 = low, end1 = mid, start2 = mid+1, end2 = high;
    mergeSort(arr, temp, start1, end1);
    mergeSort(arr, temp, start2, end2);
    int index = low;
    while(start1 <= end1 && start2 <= end2) 
        temp[index++] = arr[start1] <= arr[start2] ? arr[start1++] : arr[start2++];
    while(start1 <= end1)
        temp[index++] = arr[start1++];
    while(start2 <= end2)
        temp[index++] = arr[start2++];
    for (int i = low; i<=high; i++)
        arr[i] = temp[i];
}

4.待续....

快速幂&&快速乘:

1.快速幂:

ll quickPow(ll x, ll y) {
    if (!y)
        return 1;
    ll res = quickPow(x, y >> 1);
    res = res*res%MOD;
    if (y&1)
        res = res*x%MOD;
    return res;
}

2.快速乘:

ll solve(ll n, ll m) {
    if (!n || !m)
        return 0;
    ll res = solve(n, m>>1);
    res = res<<1 % MOD;
    if (m&1)
        res = (res+n) % MOD;
    return res;
}

 高精度:

 1.加法

void add(char* num1, char* num2, char* res)
{
    mst(res);
    int len1 = strlen(num1);
    int len2 = strlen(num2);
    reverse(num1, num1+len1);
    reverse(num2, num2+len2);
    int len, carry;
    len = carry = 0;
    for(int i=0; ii) {
        carry += i'0' : 0;
        carry += i'0' : 0;
        res[len++] = carry%10 + '0';
        carry /= 10;
    }
    if(carry)
        res[len++] = carry + '0';
    res[len] = '\0';
    reverse(res,res+len);
}

计算几何:

计算两个平行于坐标轴的矩形面积(有交叉部分)

struct poit {
    ll x, y;
} pt[4];
void change(poit &a, poit &b) {
    if (a.x > b.x)
        swap(a.x, b.x);
    if (a.y > b.y)
        swap(a.y, b.y);
}
ll S(poit a, poit b) {
    return (b.x-a.x)*(b.y-a.y);
}
ll solve() {
    for (int i = 0; i<4; ++i)
        scanf("%lld%lld", &pt[i].x, &pt[i].y);
    change(pt[0], pt[1]);
    change(pt[2], pt[3]);
    ll sum = 0;
    ll dx = min(pt[1].x, pt[3].x) - max(pt[0].x, pt[2].x);
    ll dy = min(pt[1].y, pt[3].y) - max(pt[0].y, pt[2].y);
    sum += S(pt[0], pt[1]);
    sum += S(pt[2], pt[3]);
    sum -= dx >= 0 && dy >= 0 ? dx*dy : 0;
}

计算任意多边形面积(向量叉乘):

(Xi * Y(i+1) - (Yi)*(Xi+1)) * 0.5

const int maxn = 105;
P point[maxn];
int main(void) {
    int n;
    while(cin >> n && n) {
        for (int i = 0; i)
            cin >> point[i].first >> point[i].second;
        point[n] = point[0];
        double sum = 0;
        for (int i = 0; i<=n-1; i++)
            sum += (1.0*point[i].first*point[i+1].second - 1.0*point[i+1].first*point[i].second);
        printf("%.1f\n", fabs(sum)/2.0);
    }
    return 0;
}

 搜索:

 dfs(无减枝):

bool search(int i, int m, ll sum1, ll sum2) {
    if (i == m)
        return sum2 - sum1 == sum1;
    return search(i+1, m, sum1+sogar[i], sum2) || search(i+1, m, sum1, sum2);
}   

记忆化搜索:

//举的栗子是角谷猜想的步长
//循环:
ll solve(ll x) {
    ll cnt = 1;
    while(x != 1) {
        x&1 ? x = x*3 + 1 : x >>= 1;
        ++cnt;
        if (x <= maxn && res[x])
            return cnt+res[x]-1;
    }
    return cnt;
}
    for(int i = 1; ii) {
        res[i] = solve(i);
        //printf("%lld ", res[i]);
    }
//递归:
ll solve(ll x) {
    ll cnt;
    if (x < maxn && res[x])
        return res[x];
    cnt = solve(x&1 ? x*3 + 1 : x >> 1) + 1;
    return cnt;
}
    for(int i = 1; ii)
        res[i] = solve(i);

 动态规划:

由前一个状态推出后一个状态,每个状态都是最优解,注意初始状态的选择

博弈论:

1.巴什博弈(同余理论)

巴什博奕:只有一堆n个物品,两个人轮流从中取物,规定每次最少取一个,最多取m个,最后取光者为胜。

   if(n%(m+1)==0)  cout<<"后手必胜"<<endl;  
      else cout<<"先手必胜"< 
  

2.威佐夫博弈(黄金分割)

有两堆各若干的物品,两人轮流从其中一堆取至少一件物品,至多不限,或从两堆中同时取相同件物品,规定最后取完者胜利。

解题核心就是:看两个数的差值t是不是满足  (sqrt(5)+1)/2*t==min(n1,n2);

3.尼姆博弈(异或理论)

有任意堆物品,每堆物品的个数是任意的,双方轮流从中取物品,每一次只能从一堆物品中取部分或全部物品,最少取一件,取到最后一件物品的人获胜。

解题核心:把每堆物品数全部异或起来,如果得到的值为0,那么先手必败,否则先手必胜。

4.斐波那契博弈。

有一堆物品,两人轮流取物品,先手最少取一个,至多无上限,但不能把物品取完,之后每次取的物品数不能超过上一次取的物品数的二倍且至少为一件,取走最后一件物品的人获胜。

解题核心:先手胜当且仅当n不是斐波那契数(n为物品总数)

数学:

1.1个大于1的数必定能被一个质数整除

2.互质:两个数的最大公因数是1

3.欧拉函数

通式:
 (其中p1, p2……pn为x的所有质因数,x是不为0的整数)
定义 φ(1)=1(和1 互质的数(小于等于1)就是1本身)。
注意:每种质因数只有一个。
const int maxn = 10005;
int arr[maxn];
int __elf(int n) {
    fill(arr, arr+maxn, 1);
    arr[0] = arr[1] = 0;
    int t = sqrt(maxn)+0.5;
    for (int i = 2; i<= t; i++)
        if (arr[i]) {
            for (int j = 2*i; j<=maxn; j+=i)   
                arr[j] = 0;
        }//埃氏筛选素数
    double demo = n;
    for (int i = 2; i<=n; i++) {
        if (arr[i] && !(n%i)) {
            demo *= (1-1.0/i);
            while(!(n%i))
                n /= i;
        }
    }
    return (int)((demo+1e-12)*(demo+1e-12));//欧拉函数
}

 4.数字的位数问题(对数求法)

 1.对于一个10进制数字的位数可以通过log10(n)+1得到。 那么对于b进制的位数同样可 以使用logB(n)+1得到。 那么对于logB(n!) + 1 来说, 通过换底公式,可以得到 logB(n!) = log10(n!) / log10(B),
而对于log10(n!)来说 10进制的位数为
log10(N(N-1)(N-2)...1) + 1 = log10(N) + log10(N-1) + ... log10(1)。

 5.全排列

算法模板总结_第1张图片

 

 每回规定一个数,然后分别让固定的数与没有被固定的每一位数交换,记得最后还原

         for(int i=k;i<=m;i++)
         {
             swap(list[i],list[k]);
             Perm(list,k+1,m);
             swap(list[i] , list[k]);
         }

 

 

你可能感兴趣的:(算法模板总结)