數學模板 - 計算方法


二分查找法

/* 在數組b中查找是否有數組a中的元素 */
#include <stdio.h>
#include <stdlib.h>
int comp(const void *a, const void *b)
{
	return *(int *)a - *(int *)b;
}
int main()
{
	int n, m;
	int i, j, x, y, s, mid;
	int a[100010], b[100010];
	while (scanf("%d%d", &n, &m) != EOF)
	{
		for (i = 0; i < n; i++)
			scanf("%d", &a[i]);
		for (i = 0; i < m; i++)
			scanf("%d", &b[i]);
		qsort(a, n, sizeof(int), comp);
		for (i = 0; i < m; i++)
		{
			x = n - 1;
			y = 0;
			s = 1;
			while (x >= y)
			{
				mid = (x + y) / 2;
				if (b[i] == a[mid])
				{
					printf("yes\n");
					s = 0;
					break;
				}
				else
				if (b[i] < a[mid])
					x = mid - 1;
				else
					y = mid + 1;
			}
			if (s == 1)
				printf("no\n");
		}
	}
	return 0;
}


三分查找法

bool three_divide_search(int *a, int n, int val)///數組a,長度n, a[0]-a[n-1],查找val,若存在返回true
{
    ///數組已從小到大排好序
    if (val<a[0] || val>a[n - 1]) 
        return false;
    int ll = 0, rr = n - 1;
    int mid1, mid2;
    while (ll <= rr)
    {
        int  len = rr - ll + 1;
        if (len == 1) 
            return a[ll] == val;
        else if (len == 2) 
            return (a[ll] == val) || (a[rr] == val);
        mid1 = len / 3 + ll;
        mid2 = len / 3 * 2 + ll;
        if (a[mid1] == val) 
            return true;
        else if (a[mid1] > val) 
            rr = mid1 - 1;
        else///在mid1+1,rr中找
        {
            if (a[mid2] == val) 
                return true;
            else if (a[mid2] > val)
            {
                ll = mid1 + 1;
                rr = mid2 - 1;
            }
            else ll = mid2 + 1;
        }
    }
    return false;
}


高斯消元

#include <bits/stdc++.h>
using namespace std;
const int maxn = 105;

int equ, var; ///有equ個方程,var個變元。增廣陣行數爲equ, 分別爲0到equ - 1,列數爲var + 1,分別爲0到var.
int a[maxn][maxn];
int x[maxn]; ///解集.
bool free_x[maxn]; ///判斷是否是不確定的變元.
int free_num;

void Debug(void)
{
    int i, j;
    for (i = 0; i < equ; i++)
    {
        for (j = 0; j < var + 1; j++)
            printf("%d ",a[i][j]);
        printf("\n");
    }
    printf("\n");
}

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

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

///高斯消元法解方程組(-2表示有浮點數解,但無整數解,-1表示無解,表示唯一解,大於0表示無窮解,並返回自由變元的個數)
int Gauss(void)
{
    int i, j, k, ta, tb, LCM, temp, free_x_num;
    int max_r; ///當前這列絕對值最大的行.
    int col; /// 當前處理的列.
    int free_index;///轉換爲階梯陣.
    col = 0; /// 當前處理的列.
    for (k = 0; k < equ && col < var; k++, col++)///枚舉當前處理的行.
    {///找到該col列元素絕對值最大的那行與第k行交換
        max_r = k;
        for (i = k + 1; i < equ; i++)
        {
            if (abs(a[i][col]) > abs(a[max_r][col])) 
                max_r = i;
        }
        if (max_r != k)///與第k行交換.
        {
            for (j = k; j < var + 1; j++) 
                swap(a[k][j], a[max_r][j]);
        }
        if (a[k][col] == 0)///說明該col列第k行以下全是0了,則處理當前行的下一列.
        {
            k--;
            continue;
        }
        for (i = k + 1; i < equ; i++)///枚舉要刪去的行.
        {
            
            if (a[i][col] != 0)
            {
                LCM = lcm(abs(a[i][col]), abs(a[k][col]));
                ta = LCM / abs(a[i][col]), tb = LCM / abs(a[k][col]);
                if (a[i][col] * a[k][col] < 0) tb = -tb; ///異號的情況是兩個數相加.
                for (j = col; j < var + 1; j++)
                    a[i][j] = a[i][j] * ta - a[k][j] * tb;
            }
        }
    }
    Debug();
    for (i = k; i < equ; i++)///無解的情況
    {
        if (a[i][col] != 0) 
            return -1;
    }
    if (k < var)///無窮解的情況
    {
        for (i = k - 1; i >= 0; i--)
        {
            free_x_num = 0;
            for (j = 0; j < var; j++)
            {
                if (a[i][j] != 0 && free_x[j]) free_x_num++, free_index = j;
            }
            if (free_x_num > 1) continue; ///無法求解出確定的變元.
            temp = a[i][var];
            for (j = 0; j < var; j++)
            {
                if (a[i][j] != 0 && j != free_index) temp -= a[i][j] * x[j];
            }
            x[free_index] = temp / a[i][free_index]; ///求出該變元.
            free_x[free_index] = 0; ///該變元是確定的.
        }
        return var - k; ///自由變元有var - k個
    }
    for (i = var - 1; i >= 0; i--)///唯一解的情況
    {
        temp = a[i][var];
        for (j = i + 1; j < var; j++)
        {
            if (a[i][j] != 0) 
                temp -= a[i][j] * x[j];
        }
        if (temp % a[i][i] != 0) return -2; ///說明有浮點數解,但無整數解.
        x[i] = temp / a[i][i];
    }
    return 0;
}

int main(void)
{
    int i, j;
    while (scanf("%d %d", &equ, &var) != EOF)
    {
        memset(a, 0, sizeof(a));
        memset(x, 0, sizeof(x));
        memset(free_x, 1, sizeof(free_x)); ///一開始全是不確定的變元.
        for (i = 0; i < equ; i++)
        {
            for (j = 0; j < var + 1; j++)
            {
                scanf("%d", &a[i][j]);
            }
        }
        free_num = Gauss();
        if (free_num == -1) printf("無解!\n");
        else if (free_num == -2) printf("有浮點數解,無整數解!\n");
        else if (free_num > 0)
        {
            printf("無窮多解! 自由變元個數爲%d\n", free_num);
            for (i = 0; i < var; i++)
            {
                if (free_x[i]) printf("x%d 是不確定的\n", i + 1);
                else printf("x%d: %d\n", i + 1, x[i]);
            }
        }
        else
        {
            for (i = 0; i < var; i++)
                printf("x%d: %d\n", i + 1, x[i]);
        }
        printf("\n");
    }
    return 0;
}

多項式求根

double fabs(double x)
{
    return (x < 0) ? -x : x;
}


double f(int m, double c[], double x)
{
    int i;
    double p = c[m];
    for (i = m; i > 0; i--)
        p = p * x + c[i-1];
    return p;
}

int newton(double x0, double *r,double c[], double cp[], int n,
           double a, double b, double eps)
{
    int MAX_ITERATION = 1000;
    int i = 1;
    double x1, x2, fp, eps2 = eps/10.0;

    x1 = x0;
    while (i < MAX_ITERATION)
    {
        x2 = f(n, c, x1);
        fp = f(n-1, cp, x1);
        if ((fabs(fp) < 0.000000001) && (fabs(x2) > 1.0))
            return 0;
        x2 = x1 - x2 / fp;
        if(fabs(x1-x2) < eps2)
        {
            if (x2 < a || x2 > b)
                return 0;
            *r = x2;
            return 1;
        }
        x1 = x2;
        i++;
    }
    return 0;
}

double Polynomial_Root(double c[], int n, double a, double b, double eps)///多項式係數c[],多項式度數n,求在[a,b]間的根
{
    double *cp;
    int i;
    double root;
    cp = (double *)calloc(n, sizeof(double));
    for(i = n - 1; i >= 0; i--)
        cp[i] = (i+1) * c[i+1];
    if (a > b)
    {
        root = a;
        a = b;
        b = root;
    }
    if((!newton(a, &root, c, cp, n, a, b, eps)) &&
            (!newton(b, &root, c, cp, n, a, b, eps)))
        newton((a+b)*0.5, &root, c, cp, n, a, b, eps);
    free(cp);
    if (fabs(root) < eps)
        return fabs(root);
    else
        return root;
}


發佈了73 篇原創文章 · 獲贊 276 · 訪問量 84萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章