算法--数学入门

经典数学问题

前言

本文是通过学习郑州大学ACM实验室课程总结的知识点,详细介绍了一些在算法题中可能会用到的一些基础的数学知识。

一、快速幂

**大致题目**
计算a的b次幂对m取模(mod运算)
b<=1e18

初步解题思想
如果说用需要算十进制的n次幂,就需要依次相乘进行计算。按照一般的思想,一秒内程序能运行一亿次运算即1e8次,但是b的范围的时间复杂度为O(b)b越大,时间复杂度越大,最后会超时。所以这时候就要将b转化成二进制进行运算了。

求出:
a^1
a^2
a^4
a^8
………
a^(2^n)
就有:
a^5[101(2)]=a^1*a^4
a^7[111(2)]=a^1*a^2*a^4
a^8[1000(2)]=a^8
这样算法复杂度为O(logb)……呀!大大降低了耶✌

代码实现:

#include<iostream>
using namespace std;//数据范围根据实际而定
long long quick_pow(int a, int b);
int mod;
int main()
{
    int n, m;
    cin >> n >> m>> mod ;
    long long t = quick_pow(n, m);
    cout << t << endl;
    return 0;
}
long long quick_pow(int a, int b)
{
    unsigned long long ret = 1;
    while (b) {
        if (b & 1)ret = ret * a % mod ;//b&1判断奇偶性,mod是需要取模的值
        b >>= 1;//这里相当于b/=2(向左靠齐)
        a = a * a % mod;
    }
    return ret;
}

特别注意:

a+b%m=(a%m+b%m)%m
a*b%m=(a%m*b%m)%m
a^b%m!=a%m^(b%m)

二、欧几里得算法(gcd(x,y))

题目: 求最大公约数

1.更相减损术(九章算术)

//循环
int gcd(int x,int y)
{
    while(x!=y){
        if(x>y) x=x-y;
        else y=y-x;
    }
    return x;
}
//递归
int gcd(int x,int y)
{
    if (x == y) return x;
    else {
        if (x > y) x = x - y;
        else y = y - x;
        return gcd(x, y);
    }
}

时间复杂度: O(max(x,y))

1.辗转相除法(欧几里得算法)

int gcd(int x,int y)
{
	if(!y)return x;
	else return gcd(x%y,x);
}

时间复杂度: O(log max(x,y))

三.求取整的和

题目: 求解n/1+n/2+n/3+……+n/n(这里都是取整计算)
解题思路: 这里如果是一个一个结果然后相加数据大了就很容易超时(时间复杂度为O(n)),所以应该要进行找规律后再求和。

5为例:
5/1 5/2 5/3 5/4 5/5
 5   2   1   1   110为例:
10/1 10/2 10/3 10/4 10/5 10/6 10/7 10/8 10/9 10/10
 10    5    3    2    2    1    1    1    1    1
 现在几乎可以看出基本规律了
 每一个数开根号得到的数字之后都会有重复的结果出现,那么对于重复的结果就不用一个一个计算之后再相加了
 这时候就需要解决重复区间的求解问题了
不难看出, 右端点的值都能被n整除,而左端点不一定
 每一个左端点就是上一个区间的右端点加1就好了

直接看代码实现好了,容易理解一些

#include<iostream>
using namespace std;
int main()
{
    int n;
    cin >> n ;
    int ans = 0;
    for (int l = 1, r = 1; l <= n; l = r + 1) {
        r = min(n, n / (n / l));//求右端点,也防止过界
        ans += n / l * (r - l + 1);//求和
    }
    cout << ans;
    return 0;
}

时间复杂度减为O(sqrt(n))
变式: 求n%1+n%2+n%3+……+n%n的结果
其实这里将n%t转化为n-n*n/t就好了。

总结

今天学习的主要是一些简单数学问题处理的时间优化问题,主要是一些数学思维、公式以及对数据的处理进行优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值