.快速幂.

按位与(Bitwise AND)是一种二进制运算,它逐位对两个数的二进制表示进行运算。对于每一位,只有两个相应的位都为1时,结果位才为1;否则,结果位为0。如:十进制9 & 5转化为二进制:(1001)&(0101)=0001。

>> <<

  • 左移(<<:将一个无符号整数左移n位,相当于将该数乘以2n。这是因为每向左移动一位,就相当于在数的末尾添加了一个0(在二进制表示中),这等价于乘以2。

  • 右移(>>:将一个无符号整数右移n位,相当于将该数除以2n并向下取整。这是因为每向右移动一位,就相当于去掉了数末尾的一个0(或更准确地说,是将数除以2并丢弃余数),这等价于除以2.
    无符号代表没有溢出,如果有符号为int,则可能会爆int

举个例子:
关于右移(Right Shift)和左移(Left Shift)操作的具体例子,我们将使用8位二进制数(仅为了简化说明,实际中整数可能使用更多位)来展示这些操作。

左移(Left Shift)例子

假设我们有一个无符号的8位二进制数 00001010,它等于十进制的 10。现在,我们将其向左移动2位。

原始数(二进制)00001010

左移2位后的结果

  1. 将原始数的二进制表示向左移动2位。
  2. 左侧超出的位(在这个例子中是最高位左边的所有位)将被丢弃。
  3. 在右侧新增的2位上,全部填充0。

因此,左移2位后的结果是:00101000,这等于十进制的 40

右移(Right Shift)例子

现在,我们考虑一个有符号的8位二进制数 -00001010(注意:在实际的二进制补码表示中,负数不会以这种方式直接显示,但这里为了说明右移操作,我们暂时这样表示)。在补码表示中,10001010 表示 -10(假设最高位是符号位,1表示负数)。现在,我们将其向右移动2位。

但是,由于直接以这种方式表示负数可能会导致混淆,我们将直接使用补码表示的 -10 来进行说明。

原始数(补码,二进制)11110110(这是-10在8位二进制补码表示中的值,注意这里的最高位是符号位)

右移2位(算术右移)后的结果(大多数编程语言对于有符号整数使用算术右移):

  1. 将原始数的二进制表示向右移动2位。
  2. 右侧超出的位(在这个例子中是最低位右边的所有位)将被丢弃。
  3. 在左侧新增的2位上,用符号位的值(1,因为这是一个负数)来填充。

因此,算术右移2位后的结果是:11111011,这等于十进制的 -3(在8位补码表示中)。

注意:上面的右移结果-3是基于算术右移的假设。如果使用的是逻辑右移(左侧新增的位全部填充0),则结果将是不同的正数(但在这个例子中,由于原始数是负数,逻辑右移通常不适用于表示相同的负数结果)。然而,在大多数编程语言中,对于有符号整数,右移操作默认为算术右移。

快速幂:快速的求出一个幂mod一个数的值
假设


 

题目:875. 快速幂 - AcWing题库 

代码:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long LL;

int n;

int quick_mi(int a,int b,int p)
{
    LL res=1%p;
    while(b)
    {
        //将b转化为2进制时按位与1,当b=0时,结束快速幂
        if(b&1) res=res*a%p;
        //舍弃b在二进制下的最后一位
        b = b >> 1;
        //上一个a^2%p
        a=(LL)a*a%p;
    }
    
    return res;
}

int main()
{
    scanf("%d",&n);
    
    while(n--)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        
        printf("%d\n",quick_mi(a,b,c));
    }
    
    return 0;
}

题目:876. 快速幂求逆元 - AcWing题库

 题目即是要求:b^(m-2)。

证明:
由若整数 b,m 互质,并且对于任意的整数 a,如果满足 b|a,则存在一个整数 x,使得 a/b≡a*x(mod m),则称 x 为 b 的模 m 乘法逆元,记为 b^(-1)(mod m)。等式两端约去a,得1/b≡b^(-1)(mod m)➡等式两端同时乘以b,得1≡b^(-1)*b(mod m)。也就是b*b^(-1)≡1(mod m),因为b与m互质,且m为质数,由费马小定理可得b^(m-1)≡1(mod m),也就是b*b^(m-1)≡1(mod m),所以b^(m−2) 即为 b的乘法逆元

代码:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long LL;
int n;

int quick_mi(int a,int b,int p)
{
    LL res=1;
    while(b)
    {
        if(b&1) res=res*a%p;
        a=(LL)a*a%p;
        b>>=1;
    }
    
    return res;
}

int main()
{
    scanf("%d",&n);
    while(n--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        int t=quick_mi(a,b-2,b);
//特判一下,只有当a与b互质时才成立
        if(a%b) printf("%d\n",t);
        else printf("impossible\n");
    }
    
    return 0;
    
}

 费马小定理:

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值