加法取余:
(a+b) % c = (a%c + b%c) % c
减法取余:
(a-b) % c = (a-b+c) % c
乘法取余:
法1:
(a*b) % c = [(a%c) * (b%c)] % c (前提:c*c不会溢出)
法2:
b = 2^(n) + … + 2^(i) + … //将b用二进制形式表示
(a*b) % c = [a * (2^(n) + … + 2^(i) + …)] % c = [(a*(2^n)) + …… + (a*2(i)) + ……] %c = [(a*(2^n))%c + …… + (a*2(i))%c + ……] %c
//二进制转换为10进制可以以2的权值相加(貌似是这样描述的)。比如13=(1101)2=1*2^3+1*2^2+0*2^1+1*2^0。
//同样的,当我们计算A*B的时候,也可以将B化成2^n相加的式子。
//于是,我们可以将a*b mod c转换成[a*(2^b0+2^b1+……2^bn)] mod c=[a*2^b0+a*2^b1+……a*2^bn] mod c。
//利用公式(a+b)mod c=[(a mod c)+(b mod c)]mod c这个公式进行运算。
__int64 mult_mod(__int64 a,__int64 b,__int64 c)
{
a%=c;
b%=c;
__int64 ret=0;//ret记录最终的结果
while(b)//判断不是不是为0了
{
if(b&1)//如果b的二进制中的最后一位为1 那么加上a
{
ret+=a;ret%=c;
}
a<<=1;
a%=c;//a随着b中二进制位数而扩大每次扩大两倍。
b>>=1;//b来缩小两倍 去掉最后一位 因为当前最后一位我们用完了,
}
return ret;
}
幂乘取余
法1:
(a^b) % c = ( (a%c)^(b%c) ] % c
法2:
将幂乘求余转换为乘法求余
(a*b) % c = ( (a%c) * (b%c) )%c
设 s = b/2; f = b%2. 则 b = s*2 + f
a^b = a^(s*2 + f) = [(a^s)^2] * (a^f)
f为1或0,只需递归求出a^s即可。
例:求D=C^15 % N,由于:a*b % n = ((a % n)*(b % n)) % n,所以:C1 =C*C % N
=C^2 % NC2 =C1*C % N =C^3 % NC3 =C2*C2 % N =C^6 % NC4 =C3*C % N =C^7 % NC5 =C4*C4 % N =C^14 % NC6 =C5*C % N =C^15 % N 即:对于b=15的幂模运算可分解为6 个乘模运算,归纳分析以上方法可以发现对于任意b,都可采用以下算法计算D=a^b % c:
while(b>0) { if(b%2==0) { result=(result*result)%c; // result初始值为1 b=b/2; } else { result=(result*a)%c; b=b-1; } } //继续分析会发现,要知道E何时能整除 2,并不需要反复进行减一或除二的操作,只需验证E 的二进制各位是0 还是1 就可以,所以: while(b) //求b的二进制,存放在数组int x[]中 { x[i++]=b%2; b=b>>1; //向右移位,此句也可改为b=b/2,意思一样哦 } for(j=i-1;j>=0;j--) { result=(result*result)%c; // result初始值为1 if(x[j]==1) { result=(result*a)%c; } }