(数论四)快速幂与gcd扩展杂谈

一.关于快速幂:

​ 我们要想求a^b,也就是b个a相乘,我们可以设置ans = 1,然后for循环b次,用ans累成a得到最终答案ans,这样时间复杂度是O(b)

​ 当b大于1e9,我们用上面的办法就不能在1s内求出结果了。

​ 举个栗子2^11,我们仔细观察一下:

​ ans = 2 ^ 11

​ = 2✖️2✖️2✖️2✖️2✖️2✖️2✖️2✖️2✖️2✖️2

​ = 4✖️4✖️4✖️4✖️4✖️2

​ = 16✖️16✖️4✖️2

​ = 256✖️4✖️2

​ 因此我们可以只求2,4,16,256中2,4,256组合得到2^11,而2,4,16,256可以根据平方递推得到,这样要想求得a ^ b的值时间复杂度只有O(log(b)),可以说是非常快了

​ 代码如下:

ll quick(ll a, ll b) {				//求a^b
    ll ans = 1;		
    while (b) {		
        if (b & 1) ans *= a;		//只有b为奇数时乘a,例如2^11时ans只累乘2,4,256
        b >>= 1;					//相当于b /= 2
        a *= a;						//就是上面所说的通过平方和递推,优化运算时间
    }
    return ans;
}

二. gcd扩展:

​ gcd几乎是我们刚入学接触的第一个递归了,大家想必已经熟记于心。

​ 根据gcd(a, b) = gcd (b, a % b) (a > b且 b != 0) 公式,我们只需要知道递归的终止条件,就可以写出这个递归代码。

​ 由于b != 0,所以当a % b == 0时不能继续递归。那么,当a % b == 0时,我们应该返回什么呢?谁才是a,b的最小公约数?

​ 由于a % b == 0,因此a一定是b的倍数,也就说b一定是a的因子,又因为b的最大因子是b,因此a,b的最大公约数一定是b,根据gcd(a, b) = gcd(b, a % b),我们知道b也是最初始的a,b的最大公约数。

​ 实现代码如下:

ll gcd (ll a, ll b) {					//前提条件:a,b中不存在0
    if (a < b) swap(a, b);
    //若a,b中存在0,则可添加下一行代码:
    //if(b == 0) return 0;
    return a % b == 0? b: gcd(b, a % b);
}

​ 好啦,我们说几个gcd的扩展定理:

​ (1).gcd (ka, kb) = k✖️gcd(a, b)

​ (2).lcm(ka, kb) = k ✖️lcm(a, b)

​ (3).lcm(s / a, s / b) = s / gcd(a, b)

​ 有一些题目可通过这些扩展定理来少走很多弯路~

​ Over~

转载请注明出处!!!

如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值