日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

發布時間:2023/12/15 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 疯子的算法总结(一) 位运算(快速幂、快速乘) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、預備知識(補碼,反碼)

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

二、基本操作

1、按位與(&)

參加運算的兩個數,換算為二進制(0、1)后,進行與運算。只有當相應位上的數都是1時,該位才取1,否則該為為0。

將10與-10進行按位與(&)運算:

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

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

參加運算的兩個數,換算為二進制(0、1)后,進行或運算。只要相應位上存在1,那么該位就取1,均不為1,即為0。

將10與-10進行按位或(|)運算:

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

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

參加運算的兩個數,換算為二進制(0、1)后,進行異或運算。只有當相應位上的數字不相同時,該為才取1,若相同,即為0。

將10與-10進行按位異或(^)運算:

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

所以:10 ^ -10 = 1111 1111 1111 1100
可以看出,任何數與0異或,結果都是其本身。利用異或還可以實現一個很好的交換算法,用于交換兩個數,算法如下:

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

4、取反(~)

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

0000 0000 0000 1010
1111 1111 1111 0101

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

參加運算的兩個數,換算為二進制(0、1)后,進行左移運算,用來將一個數各二進制位全部向左移動若干位。

對10左移2位(就相當于在右邊加2個0):

0000 0000 0000 1010
0000 0000 0010 1000

所以:10 << 2 = 0000 0000 0010 1000 = 40
注意,觀察可以發現,左移一位的結果就是原值乘2,左移兩位的結果就是原值乘4。

6、右移(>>)

參加運算的兩個數,換算為二進制(0、1)后,進行右移運算,用來將一個數各二進制位全部向右移動若干位。

對10右移2位(就相當于在左邊加2個0):

0000 0000 0000 1010
0000 0000 0000 0010

所以:10 >> 2 = 0000 0000 0000 0010 = 2
注意,觀察可以發現,右移一位的結果就是原值除2,左移兩位的結果就是原值除4,注意哦,除了以后沒有小數位的,都是取整。

三、延伸操作

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; //防止在對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; //(計算機加法比乘法快,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優化版

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學習中,還有更多的操作可以用位運算。

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。