背景知识——模运算
1.定义:对任意实数x,y,可以有
2.符号:%
模运算是一种二元运算[二元运算是由两个元素形成第三个元素(更一般:两个集合形成第三个集 合)的一种规则,是作用于两个对象的运算]
3.范围:
y=0时,为避免0作除数,定义x mod 0=x
4.运算法则:
结合律:
交换律:
分配律:
和差和乘法均满足分配律,但除法不满足,由此引出乘法逆元,即数论倒数
一.乘法逆元
1.定义:若在mod p意义下,对于一个整数a,有a*x1(mod p),那么这个整数x即为a的乘法逆元,同时a也为x的乘法逆元
逆元,取最小正整数
2.充分必要条件:a存在模p(mod p)的充要条件是gcd(a,p)=1,即a与p互质
简单说,a与p互质,a才有关于p的逆元
mod p,即模 p,即%p
a*x1(mod p),即a*x与1在模p下同余,其中x叫做a的关于p的逆元,记为inv(a)=x
这里把x看成a的倒数,不过是加了一个求余的条件,而x不一定等于
例:4*3%11=1,则3是4关于11的逆元(或4是3关于11的逆元),这里的3跟 效果一样,所以才叫数论倒数
gcd(a,p)=1,即a与p的最大公约数是1,即a与p互质 (a就不是p的倍数,详见费马小定理第二条)
3.应用:求(a/b)%p等同于a*(b的逆元)%p
证明:设b的逆元为x,则b*x1(mod p),(表示数论倒数),则(a/b)%p=(a*x)%p
设(a/b)%p=m,两边同乘以b,得 a%p=m*b%p
则am*b (%p),两边同乘以x,a*xm*b*x (%p)
则a*xm(%p)
4.求解逆元:费马小定理(p为质数)、扩展欧几里得、线性递推......
二.费马小定理
费马小定理:假如a是一个整数,p是一个质数,那么
1.如果a是p的倍数,
2.如果a不是p的倍数,
(比照逆元定义可知,是a的逆元)
注意上式写成等号应该是这样:
(因为是一个非常大的数,而逆元取的是最小正整数,所以要模p)
同余式: 表示a和b对模n同余,即正整数a-b能被n整除
例:a=5,p=3,则a的逆元,检验:5*2%3=1,即
计算机中的p很大,在求时通常使用快速幂求解
例:求 1.连乘16个2,对P而言方法1的复杂度为
2.快速幂:,只需乘4次,复杂度为
整数快速幂
#include<stdio.h>
typedef long long LL;
int p=9973;
LL qpow(LL B,LL p-2)
{
LL ans=1;
LL a=B;
LL b=p-2;
while(b)
{
if(b&1)
{
ans=(ans*a)%p;
}
a=(a*a)%p;
b>>=1; //位运算:b右移一位,相当于b/=2。
}
return ans;
}
1.">>"、"<<":右移、左移运算符。
用来将一个数的各二进制位全部右/左移若干位。因为位运算比×运算快,所以可对一下代 码进行优化,还可利用右/左移运算符计算a的第b个二进制位是什么。
右移一位相当于除以2,左移一位相当于乘以2;
右移两位相当于除以,左移两位相当于乘以。
计算:8>>18/2=4 8<<n8*.
<<(左移) | >>(带符号右移) | >>>(无符号右移) | |
运算规则 | 按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。 | 按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1。 | 按二进制形式把所有的数字向右移动对应位数,低位移出(舍弃),高位的空位补零。对于正数来说和带符号右右移相同,对于负数来说不同。 其他结构和>>相似。 |
语法格式 | 需要移位的数字 << 移位的次数 例如: 3 << 2,则是将数字3左移2位 | 需要移位的数字 >> 移位的次数 例如11 >> 2,则是将数字11右移2位 | |
计算过程 | 3 << 2 首先把3转换为二进制数字0000 0011,然后把该数字高位(左侧)的两个零移出,其他的数字都朝左平移2位,最后在低位(右侧)的两个空位补零。则得到的最终结果是0000 1100,则转换为十进制是12。 | 11的二进制形式为:0000 1011,然后把低位的最后两个数字移出,因为该数字是正数,所以在高位补零。则得到的最终结果是0000 0010。转换为十进制是2。 | |
数学意义 | 在数字没有溢出的前提下,对于正数和负数,左移一位都相当于乘以2的1次方,左移n位就相当于乘以2的n次方。 | 右移一位相当于除2,右移n位相当于除以2的n次方。这里是取商哈,余数就不要了。 |