转自:http://hi.baidu.com/xuhanqiu/item/4ccf1bea93fd4ec6bbf37d12首先想说的是, a%b. 一般都是a>0,b>0 或 a<0, b>0. 其它情况就不要考虑了。 下面说明了为这么只需要考虑这两种情形。 其次,本文总结了模运算对加法、减法、乘法的封闭性。讨论是除法与模运算之间的关系,从而得到一个实用的公式。========================正文(精华在文末...)======================== 在数学中,我们做取模运算(a%b)都是假设a,b>0的.但在编程处理时,我们经常会碰到a<0,b<0的情况, 而且计算机自己处理取模运算时,与我们数学求出来的结果还不一样 ( 我们想要的结果就是按数学方法计算出来的), 所以要搞清楚计算机求出来的结果与我们想要的结果之间的联系!!1.先只考虑a<0的情况 (b>0)
a=-106 b=105 数学上: a % b = 104 计算机: a % b = -1
a=-312 b=105 数学上: a % b = 3 计算机: a % b = -102在计算机中(使用VC++)做取模运算时:
#include int main()
{
int x;
int y = 105;for (x=110; x>=-110; x--)
printf("%d %% %d = %d
", x, y, x%y);return 0;
}
经过大量测试发现:
若我们不能保证a一定大于0时,结果为负时,我们加上一个b就与我们数学中求得的结果是一样的. 参加上面介绍的第二个例子 a = -312时2.不需要考虑b<0, 因为计算机是把它当成-b来处理,所以与b>0一样
#include int main()
{
int x;
int y = -5;
for (x=10; x>=-10; x--)
printf("%d %% %d = %d
", x, y, x%y);printf("=============================
");
y = 5;
for (x=10; x>=-10; x--)
printf("%d %% %d = %d
", x, y, x%y);
return 0;
}===========================
模运算有很多性质
(a+b)%n = (a%n + b%n) % n;
(a*b)%n = ((a%n)*(b%n)) % n;
(a-b)%n = (a+(-b))%n = ( (a%n) + ((-b)%n) ) % n 若结果为负,加上n即可
(a/b)%n 没有这个性质了,呵呵~~ 取模运算对加法、减法、乘法都封闭,所以我们很容易计算(a+b)mod m,(a-b)mod m,(a*b)mod m。但是,要计算(a/b) mod m就不是那么容易了。 下面首先介绍一个通用公式: (a / b) % m = ( a % (m*b)) / b --- 推导见文末除了上面的公式,还有一些特殊的情况, eg: m和b互素的时候。1. 当gcd(b,m) = 1, 有性质: (a/b)%m = (a*b^-1)%m, 其中b^-1是b模m的逆元.求出b相对于m的逆元b^(-1),即b*(b^(-1)) = 1 (mod m)。有b*b^(-1) - km = 1,其中k是一整数. 用Extended Euclid算法可以求出`b^(-1)。然后计算a*b^(-1) mod m = ( (a%m) * (b^(-1)%m ) % m; 其值与(a/b) mod m相同推导:a/b = x (mod m) --两边同乘一个数--> a = bx (mod m) ---x=b^-1a-> a = (b^-1) ba (mod m)再利用b^-1*b = 1(mod m) . 所以可以得出 x = b^-1*a是成立的。 所以 (a/b) mod m 的解与 (a*b^-1)%m的解是一样的。 而后着可以利用模对乘法的线性性2. 当gcd(b,m)!=1时怎么办? 此时方程`b*b^(-1) - km = 1`无整数解,求逆元的方法失效了。----目前自己只会上面的那个通用公式来求。上面的公式推导如下(目标是求 (a/b) % m):由于b | a, 所以a = k, 然后将k对m做带余法法,得: a = tmb+rb(其中r
(a / b) % m = (tm+r) % m = r, 现在目标就是r。我们可以等价的求出r。由于rhttp://acm.fzu.edu.cn/contest/cproblem.php?cid=1073&pid=1Given A,B,C, You should quickly calculate the result of A^B mod C. (1<=A,B,C<2^63).A^B mod C:---------呵呵,刚刚解决这个题,两次二分(多出来的一次二分是解决(A*B)%C的溢出问题)。这也说明通用公式还是有很多用武之地的,只要m*b<2^63 -- (当然,更大时怎么办,高精度么?待整理)