日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

疯子的算法总结(一) 位运算(快速幂、快速乘)

發(fā)布時(shí)間:2023/12/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 疯子的算法总结(一) 位运算(快速幂、快速乘) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、預(yù)備知識(shí)(補(bǔ)碼,反碼)

計(jì)算機(jī)通過二進(jìn)制表示整形數(shù),比如int型32位有符號(hào)整形數(shù):
1表示為:0000…00001(共32位)
-1表示為:1111…1111(共32位)
補(bǔ)碼計(jì)算法定義:非負(fù)數(shù)的補(bǔ)碼是其原碼本身;
負(fù)數(shù)的補(bǔ)碼是其絕對(duì)值的原碼最高位符號(hào)位不變,其它位取反,再加1。
表示原因:計(jì)算機(jī)邏輯運(yùn)算沒有減法,-1+1最高為溢出,剩余0000000000(32位)即為0;
則有a-b=a+b的(補(bǔ)碼);
計(jì)算方式
-1表示原碼為100…0001(32位),最高位位符號(hào)位。
-1的反碼表示為:1111…110(32位),除符號(hào)位按位取反。
-1的補(bǔ)碼表示為:1111…1111(32位),反碼+1。
正數(shù)的補(bǔ)碼為自己本身。
例子:
100的補(bǔ)碼?00000000000000000001100100?
-30的補(bǔ)碼 11111111111111111111111100010?
100+(-30)=000000000000000000?01000110?
轉(zhuǎn)換成10進(jìn)制為70;

二、基本操作

1、按位與(&)

參加運(yùn)算的兩個(gè)數(shù),換算為二進(jìn)制(0、1)后,進(jìn)行與運(yùn)算。只有當(dāng)相應(yīng)位上的數(shù)都是1時(shí),該位才取1,否則該為為0。

將10與-10進(jìn)行按位與(&)運(yùn)算:

0000 0000 0000 1010
1111 1111 1111 0110
0000 0000 0000 0010

所以:10 & -10 = 0000 0000 0000 0010
2、按位或(|)

參加運(yùn)算的兩個(gè)數(shù),換算為二進(jìn)制(0、1)后,進(jìn)行或運(yùn)算。只要相應(yīng)位上存在1,那么該位就取1,均不為1,即為0。

將10與-10進(jìn)行按位或(|)運(yùn)算:

0000 0000 0000 1010
1111 1111 1111 0110
1111 1111 1111 1110

所以:10 | -10 = 1111 1111 1111 1110
3、按位異或(^)

參加運(yùn)算的兩個(gè)數(shù),換算為二進(jìn)制(0、1)后,進(jìn)行異或運(yùn)算。只有當(dāng)相應(yīng)位上的數(shù)字不相同時(shí),該為才取1,若相同,即為0。

將10與-10進(jìn)行按位異或(^)運(yùn)算:

0000 0000 0000 1010
1111 1111 1111 0110
1111 1111 1111 1100

所以:10 ^ -10 = 1111 1111 1111 1100
可以看出,任何數(shù)與0異或,結(jié)果都是其本身。利用異或還可以實(shí)現(xiàn)一個(gè)很好的交換算法,用于交換兩個(gè)數(shù),算法如下:

a = a ^ b;
b = b ^ a;
a = a ^ b;

4、取反(~)

參加運(yùn)算的兩個(gè)數(shù),換算為二進(jìn)制(0、1)后,進(jìn)行取反運(yùn)算。每個(gè)位上都取相反值,1變成0,0變成1。
對(duì)10進(jìn)行取反(~)運(yùn)算:

0000 0000 0000 1010
1111 1111 1111 0101

所以:~10 = 1111 1111 1111 0101
5、左移(<<)

參加運(yùn)算的兩個(gè)數(shù),換算為二進(jìn)制(0、1)后,進(jìn)行左移運(yùn)算,用來將一個(gè)數(shù)各二進(jìn)制位全部向左移動(dòng)若干位。

對(duì)10左移2位(就相當(dāng)于在右邊加2個(gè)0):

0000 0000 0000 1010
0000 0000 0010 1000

所以:10 << 2 = 0000 0000 0010 1000 = 40
注意,觀察可以發(fā)現(xiàn),左移一位的結(jié)果就是原值乘2,左移兩位的結(jié)果就是原值乘4。

6、右移(>>)

參加運(yùn)算的兩個(gè)數(shù),換算為二進(jìn)制(0、1)后,進(jìn)行右移運(yùn)算,用來將一個(gè)數(shù)各二進(jìn)制位全部向右移動(dòng)若干位。

對(duì)10右移2位(就相當(dāng)于在左邊加2個(gè)0):

0000 0000 0000 1010
0000 0000 0000 0010

所以:10 >> 2 = 0000 0000 0000 0010 = 2
注意,觀察可以發(fā)現(xiàn),右移一位的結(jié)果就是原值除2,左移兩位的結(jié)果就是原值除4,注意哦,除了以后沒有小數(shù)位的,都是取整。

三、延伸操作

1.快速冪(快速模冪)
①求a^b:

int pow(int a, int k) { int ans = 1;while(k) {if(k &1) ans *= a; //判斷奇偶只用判斷最后一位比取模快a *= a;k >>=1; //比除法快多了}return ans; }

②求a^b%p

int pow_mod(int a, int k,int mod) { int ans = 1%mod;while(k) {if(k &1) ans =(long long) ans*a%mod; //防止在對(duì)P取模前溢出a = (long long)a*a%mod;k >>=1; //比除法快多了}return ans;}

例題:BZOJ1008
2.快速乘法
方法①

long long quickMul(long long a,long long b,long long mod) {long long ans=0;while(b){if(b&1) ans=(ans+a)%mod;a=(a+a)%mod; //(計(jì)算機(jī)加法比乘法快,a+a比a*2快)b>>=1;}return ans; }

方法②:高效算法

long long quickMul(long long a,long long b,long long mod) {a%=mod;b%=mod;long long ans=0;while(b){if(b&1){ans+=a;if(ans>=mod)ans-=mod;}b>>=1;a<<=1;if(a>=mod) a-=mod;}return ans; }

方法③:使用long double優(yōu)化版

long long quickMul(long long a,long long b,long long mod) {a%=mod;b%=mod;long long c=(long double) a*b/mod;long long ans=a*b-c*mod;if(ans<0) ans+=mod;else if(ans>=mod) ans-=mod;return ans}

在這里僅提到部分操作,在ACM學(xué)習(xí)中,還有更多的操作可以用位運(yùn)算。

總結(jié)

以上是生活随笔為你收集整理的疯子的算法总结(一) 位运算(快速幂、快速乘)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。