权当笔记!
(一)归并排序:
#include <stdio.h> #include <stdlib.h> #include <string> typedef long long LL; using namespace std; /* T(n) = 2T(n/2) + ⊙(n) = nlog(n) */ void Merge_sort(int *A,int x,int y,int *t) /* x表示左闭,y表示右开 */ { if(y - x > 1){ int m = x + (y - x) / 2; int p = x,q = m,i = x; Merge_sort(A, x, m, t); Merge_sort(A, m, y, t); while(p < m || q < y){ if(q >= y || (p < m && A[p] <= A[q])) t[i++] = A[p++]; else t[i++] = A[q++]; } for(i=x; i<y; i++) A[i] = t[i]; } } int main() { int t[15]; int s[] = {4, 1, 7, 6, 3, 8, 2, 5, 0, 9}; Merge_sort(s, 0, 10, t); int i; for(i=0; i<10; i++) printf("%d ", s[i]); printf("\n"); return 0; }
用递归体会一下其中的分治思想,当然也可以用while循环解决!
#include <stdio.h> #include <stdlib.h> #include <string> typedef long long LL; using namespace std; /* T(n) = T(n/2) + ⊙(1) = log(n) */ int Binary_find(int key, int left, int right, int *a) { int mid = left + (right - left) / 2; if(a[mid] == key) return mid; else if(a[mid] > key) return Binary_find(key, left, mid - 1, a); else if(a[mid] < key) return Binary_find(key, mid + 1, right, a); } int main() { int a[] = {1, 3, 4, 6, 7, 9, 12, 14, 23, 24}; int i; int ans; for(i=0; i<8; i++){ ans = Binary_find(a[i], 0, 7, a); printf("%d\n", ans); } return 0; }
库函数<math.h>里面的double pow(double x, double y) 更加完美,指数可以是浮点型。这里手写个double Pow(double x, int n)。
#include <stdio.h> #include <stdlib.h> #include <string> typedef long long LL; using namespace std; /* T(n) = T(n/2) + ⊙(1) = log(n) */ double f(double x, int n) { if(1 == n) return x; int mid = (n>>1); double s = f(x, mid); if(n & 1) return s * s * x; else return s * s; } double Pow(double x, int n) { if(0 == x && n > 0) return 0.0; else if(0 == n) return 1.0; else if(n > 0) return f(x, n); else if(n < 0) return (1/f(x, -n)); } int main() { double x; int n; while(~scanf("%lf%d", &x, &n)){ printf("%0.6lf\n", Pow(x, n)); printf("%0.6lf\n", pow(x, n)); } }
递归是最愚蠢的做法,迭代可以是 ⊙(n) 的复杂度,矩阵快速幂可达到 ⊙(log(n)) 的复杂度。
F(n) 表示第n个斐波那契数则有这样的关系:
矩阵 F(N+1) F(N) = 矩阵 1 1 的 N 次方
F(N) F(N-1) 1 0
可用数学归纳法证明。所以结果就是普通的矩阵快速幂。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> #include <iostream>
using namespace std;
int cnt; /* 时间复杂度为指数级 */ LL Fibonacci(int n) { cnt++; if(1 == n || 2 == n) return 1; else return Fibonacci(n - 1) + Fibonacci(n - 2); } /* T(n) = ⊙(n) */ LL Fibonacci1(int n) { LL a[100000]; a[1] = a[2] = 1; int i; for(i=3; i<=n; i++) a[i] = a[i - 1] + a[i - 2]; return a[n]; } typedef struct { LL a[2][2]; }Matrix; Matrix A, B; Matrix Matrix_mul(Matrix X, Matrix Y) { Matrix tmp; memset(tmp.a, 0, sizeof(tmp)); int i,j,k; for(i=0; i<2; i++) for(j=0; j<2; j++) for(k=0; k<2; k++) tmp.a[i][j] += X.a[i][k] * Y.a[k][j]; return tmp; } /* T(n) = ⊙(logn) */ LL Fibonacci2(int n) { A.a[0][0] = 1; A.a[0][1] = 1; A.a[1][0] = 1; A.a[1][1] = 0; B.a[0][0] = 1; B.a[0][1] = 0; B.a[1][0] = 0; B.a[1][1] = 1; while(n) { if(n & 1) B = Matrix_mul(B, A); A = Matrix_mul(A, A); n >>= 1; } return B.a[0][0]; } int main() { int i; int text = 4; LL ans = Fibonacci1(text); //long begtime = clock(); FILETIME beg,end; GetSystemTimeAsFileTime(&beg); for(i=0; i<100000; i++) Fibonacci2(text); GetSystemTimeAsFileTime(&end); long time = (end.dwLowDateTime-beg.dwLowDateTime); //long endtime = clock(); //cout<<endtime - begtime<<endl; cout << time <<endl; cout << ans <<endl; }
参考了网上的做法,重写了此矩阵乘法,用了一个4阶矩阵验证。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> #include <iostream> typedef long long LL; using namespace std; typedef int INT; #define N 4 typedef struct matrix { INT a[N][N]; matrix() { memset(a, 0, sizeof(a)); } }Matrix; void Matrix_mul(const Matrix A, const Matrix B, Matrix &C) { memset(C.a, 0, sizeof(C.a)); int i,j,k; for(i=0; i<2; i++) for(j=0; j<2; j++) for(k=0; k<2; k++) C.a[i][j] += A.a[i][k] * B.a[k][j]; } void Matrix_add(const int n, const Matrix A, const Matrix B, Matrix &C) { memset(C.a, 0, sizeof(C.a)); int i,j; for(i=0; i<n; i++) for(j=0; j<n; j++) C.a[i][j] = A.a[i][j] + B.a[i][j]; } void Matrix_sub(const int n, const Matrix A, const Matrix B, Matrix &C) { memset(C.a, 0, sizeof(C.a)); int i,j; for(i=0; i<n; i++) for(j=0; j<n; j++) C.a[i][j] = A.a[i][j] - B.a[i][j]; } void Strassen(INT n, const Matrix A, const Matrix B, Matrix &C) { Matrix A11, A12, A21, A22; Matrix B11, B12, B21, B22; Matrix C11, C12, C21, C22; Matrix M1, M2, M3, M4, M5, M6, M7; Matrix At, Bt, Mt, Mt1; if(2 == n) Matrix_mul(A, B, C); else{ n /= 2; int i, j; for(i=0; i<n; i++) for(j=0; j<n; j++){ A11.a[i][j] = A.a[i][j]; A12.a[i][j] = A.a[i][j + n]; A21.a[i][j] = A.a[i + n][j]; A22.a[i][j] = A.a[i + n][j + n]; B11.a[i][j] = B.a[i][j]; B12.a[i][j] = B.a[i][j + n]; B21.a[i][j] = B.a[i + n][j]; B22.a[i][j] = B.a[i + n][j + n]; } Matrix_sub(n, A12, A22, At); Matrix_add(n, B21, B22, Bt); Strassen(n, At, Bt, M1); Matrix_add(n, A11, A22, At); Matrix_add(n, B11, B22, Bt); Strassen(n, At, Bt, M2); Matrix_sub(n, A11, A21, At); Matrix_add(n, B11, B12, Bt); Strassen(n, At, Bt, M3); Matrix_add(n, A11, A12, At); Strassen(n, At, B22, M4); Matrix_sub(n, B12, B22, Bt); Strassen(n, A11, Bt, M5); Matrix_sub(n, B21, B11, Bt); Strassen(n, A22, Bt, M6); Matrix_add(n, A21, A22, At); Strassen(n, At, B11, M7); /* sub_C */ Matrix_add(n, M6, M1, Mt); Matrix_add(n, Mt, M2, Mt1); Matrix_sub(n, Mt1, M4, C11); Matrix_add(n, M5, M4, C12); Matrix_add(n, M6, M7, C21); Matrix_sub(n, M5, M3, Mt); Matrix_add(n, Mt, M2, Mt1); Matrix_sub(n, Mt1, M7, C22); for(i=0; i<n; i++) for(j=0; j<n; j++){ C.a[i][j] = C11.a[i][j]; C.a[i][j + n] = C12.a[i][j]; C.a[i + n][j] = C21.a[i][j]; C.a[i + n][j + n] = C22.a[i][j]; } } } int main() { Matrix A, B, C; A.a[0][0] = 1; A.a[0][1] = 0; A.a[0][2] = 2; A.a[0][3] = 1; A.a[1][0] = 0; A.a[1][1] = 3; A.a[1][2] = 1; A.a[1][3] = 2; A.a[2][0] = 0; A.a[2][1] = 0; A.a[2][2] = 2; A.a[2][3] = 2; A.a[3][0] = 2; A.a[3][1] = 3; A.a[3][2] = 0; A.a[3][3] = 1; B.a[0][0] = 2; B.a[0][1] = 1; B.a[0][2] = 0; B.a[0][3] = 0; B.a[1][0] = 0; B.a[1][1] = 1; B.a[1][2] = 1; B.a[1][3] = 1; B.a[2][0] = 1; B.a[2][1] = 0; B.a[2][2] = 2; B.a[2][3] = 2; B.a[3][0] = 3; B.a[3][1] = 0; B.a[3][2] = 2; B.a[3][3] = 1; Strassen(N, A, B, C); int i,j; for(i=0; i<N; i++){ for(j=0; j<N; j++) printf("%-4d", C.a[i][j]); printf("\n"); } return 0; }