数学模板 - 计算方法


二分查找法

/* 在数组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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值