【算法】同餘定理及快速冪求模

定義及其性質

定以
數論中的重要概念。給定一個正整數m,如果兩個整數a和b滿足a-b能夠被m整除,即m/(a-b)得到一個整數,那麼就稱整數a與b對模m同餘,記作a≡b(mod m)。對模m同餘是整數的一個等價關係。

兩個整數a、b,若它們除以整數m所得的餘數相等,則稱a與b對於模m同餘或a同餘於b模m。
性質
1.反身性:a≡a (mod m);
2.對稱性:若a≡b(mod m),則b≡a (mod m);
3.傳遞性:若a≡b(mod m),b≡c(mod m),則a≡c(mod m);
4.同餘式相加:若a≡b(mod m),c≡d(mod m),則a±c≡b±d(mod m);
5.同餘式相乘:若a≡b(mod m),c≡d(mod m),則ac≡bd(mod m)。
6.冪運算:如果 a≡b(mod m),那麼an≡bn(mod m);
7.除法:若 ac≡bc(mod m),c≠0則 a≡b(mod m/gcd(c,m)),其中gcd(c,m)表示c和m的最大公約數,
8.若a≡b(mod mi),(i=1,2…n) 則a≡b(mod [m1,m2,…mn]) ,其中[m1,m2,…mn] 表示m1,m2,…mn的最小公倍數。
應用

(a + b) % m = (a % m + b % m) % m

設 a = k1 * m + r1,b = k2 * m + r2
則 (a + b) % m = ((k1 * m + r1) + (k2 * m + r2)) % m
= ((k1 + k2) * m + (r1 + r2)) % m
= (r1 + r2) % m
= (a % m + b % m) % m
所以 (a + b) % m = (a % m + b % m) % m

(a * b) % m = ((a % m) * (b % m)) % m

設 a = k1 * m + r1,b = k2 * m + r2
則 (a * b) % m = ((k1 * m + r1) * (k2 * m + r2)) % m
= (k1 * k2 * m^2 + (k1 * r2 + k2 * r1) * m + r1 * r2) % m
= (r1 * r2) % m
= ((a % m) * (b % m)) % m
所以 (a * b) % m = ((a % m) * (b % m)) % m


大數的高精度對單精度取模

大數在編程中表示超過32位二進制位的數,不能直接求模,只能對其“分塊”求模

應用公式(a + b) % m = (a % m + b % m) % m可做到邊運算邊取餘
一個高精度數對一個數取餘,可以把高精度數看成各位數的權值與個位數乘積的和。
比如1234 = ((1 * 10 + 2) * 10 + 3) * 10 + 4,對這個數進行取餘運算就是上面基本加和乘的應用每步求模得1234%n = ((((1 * 10)%n+2%n)%n * 10%n+3%n)%n * 10%n+4%n)%n
代碼實現

 #include<stdio.h>//大數求餘,其中n爲除數 ,數組a[]用於存大數
char a[1000];
int main()
int i,j,k,m,n;
{
	while(scanf("%s%d",a , &n) != EOF)
	{
		m=0;
		for(i=0; a[i] != '\0'; i++)
			m = ((m*10)%n + (a[i] - '0')%n)%n;
		printf("%d\n", m);               //輸出求得的mod值
	}
return 0;
}

這是在10進制下的做法,千進制也同理,* 10改爲 * 1000就可以了


快速冪取模(次方求模)

對次方數求模一般方法需要試除法,運行較慢或者a,b超出計算機存儲範圍
對於511的指數11可以變爲2進制數1011即
11 = 1 * 23 +0 * 22+1 * 21+1 * 20
則511可轉化爲58*52*51
運用公式 (a * b) % m = ((a % m) * (b % m)) % m
代碼實現(函數部分)

int fun(int a, int b, int mode)   //a爲底數,b爲指數的二進制形式,mode爲除數
{
	int sum = 1;//sum用於記錄取模結果
	while(b != 0)
	{
		if(b&1) //用於判斷b的末位是否爲1
		{
			sum = (sum*a)%mode;  
			b--;	
		}
		a = (a*a)%mode; //底數的1次方,2次方依次……變化
		b /= 2;//去掉上一位(二進制中) 
	}                       
	return sum;
}

&是C的位運算符的一種,進行邏輯與運算,格式是:變量1&變量2,進行計算時,將會把類型提升爲int。二進制運算符&通過對兩個操作數一位一位的比較產生一個新的值,對於每個位,只有兩個操作數的對應位都爲1時結果才爲1.如10000001&11000000的結果爲“10000000”


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章