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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

起床困难综合征(位运算)

發(fā)布時(shí)間:2024/1/18 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 起床困难综合征(位运算) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

具體說(shuō)來(lái),drd 的防御戰(zhàn)線由 nn 扇防御門(mén)組成。每扇防御門(mén)包括一個(gè)運(yùn)算 opop 和一個(gè)參數(shù) tt,其中運(yùn)算一定是 OR,XOR,AND 中的一種,參數(shù)則一定為非負(fù)整數(shù)。如果還未通過(guò)防御門(mén)時(shí)攻擊力為 x,則其通過(guò)這扇防御門(mén)后攻擊力將變?yōu)?x op t。最終 drd 受到的傷害為對(duì)方初始攻擊力 x 依次經(jīng)過(guò)所有 nn 扇防御門(mén)后轉(zhuǎn)變得到的攻擊力。
由于 atm 水平有限,他的初始攻擊力只能為 0 到 m 之間的一個(gè)整數(shù)(即他的初始攻擊力只能在 0,1,…,m 中任選,但在通過(guò)防御門(mén)之后的攻擊力不受 m 的限制)。為了節(jié)省體力,他希望通過(guò)選擇合適的初始攻擊力使得他的攻擊能讓 drd 受到最大的傷害,請(qǐng)你幫他計(jì)算一下,他的一次攻擊最多能使 drd 受到多少傷害。
輸入格式
輸入文件的第 1 行包含 2 個(gè)整數(shù),依次為 n,m,表示 drd 有 n 扇防御門(mén),atm 的初始攻擊力為 0 到 m 之間的整數(shù)。
接下來(lái) n 行,依次表示每一扇防御門(mén)。每行包括一個(gè)字符串 op 和一個(gè)非負(fù)整數(shù) t,兩者由一個(gè)空格隔開(kāi),且 op 在前,t在后,op 表示該防御門(mén)所對(duì)應(yīng)的操作,t 表示對(duì)應(yīng)的參數(shù)。
輸出格式
輸出一行一個(gè)整數(shù),表示 atm 的一次攻擊最多使 drd 受到多少傷害。
輸入輸出樣例
輸入 #1復(fù)制
3 10
AND 5
OR 6
XOR 7
輸出 #1復(fù)制
1
說(shuō)明/提示
【樣例說(shuō)明】
atm 可以選擇的初始攻擊力為 0,1,…,10。
假設(shè)初始攻擊力為 4,最終攻擊力經(jīng)過(guò)了如下計(jì)算
4 AND 5=4
4 OR 6=6
6 XOR 7=1
類(lèi)似的,我們可以計(jì)算出初始攻擊力為 1,3,5,7,9 時(shí)最終攻擊力為 0,初始攻擊力為 0,2,4,6,8,10 時(shí)最終攻擊力為 1,因此atm的一次攻擊最多使drd受到的傷害值為 1。
2 <=n<=10 ^ 5,2<=m<=10 ^ 9

知識(shí)點(diǎn):
1、與1異或,可以使特定位翻轉(zhuǎn) ,與0異或,保留其值 0101 0101 ^ 1111 0000 = 1010(翻轉(zhuǎn)) 0101(保留)
2、相同的值異或?yàn)? a^a=0
3、1除了最低位,其他位都為0,所以按位與結(jié)果取決于n最后一位,如果n最后一位是1,則結(jié)果為1,反之結(jié)果為0
4、0的二進(jìn)制是: 00000000…………
-1的二進(jìn)制是:1111111111…………
只用0和-1進(jìn)行位運(yùn)算,就可以得到任何一位的任何情況進(jìn)行位運(yùn)算的結(jié)果

思路:
1、目的是從(0,m)中選出一個(gè)最好的初始攻擊數(shù)據(jù)K,然后通過(guò)n道門(mén)之后,數(shù)最大
2、如果把m中的每個(gè)數(shù)據(jù)都枚舉一遍,肯定不可以,所以反向思考得到最佳數(shù)據(jù)
3、過(guò)程肯定是將初始值K,攻擊n道門(mén),將K轉(zhuǎn)化成二進(jìn)制后,其實(shí)也就是二進(jìn)制數(shù)上的每一位數(shù)都攻擊過(guò)n道門(mén)(位運(yùn)算的性質(zhì),每個(gè)數(shù)之間相互不影響)
可以通過(guò)一個(gè)函數(shù):

int t[N]; // t 存輸入的 n 個(gè)數(shù) string op[N]; // op 存 n 個(gè)數(shù)對(duì)應(yīng)的操作 bool jisuan(bool x, int j) // jisuan 用于計(jì)算 x 經(jīng)過(guò)所有數(shù)的第 j 位操作后所得到的結(jié)果 {for (int i = 0; i < n; i ++ ) // 當(dāng)前數(shù)字,遍歷n道門(mén)if (op[i] == "OR") x |= t[i] >> j & 1; else if (op[i] == "XOR") x ^= t[i] >> j & 1; else x &= t[i] >> j & 1; return x; }

4、接下來(lái)就是把所有二進(jìn)制位數(shù)遍歷一遍,因?yàn)楸绢}中 m 最大是 10 ^ 9,log2(10 ^ 9) < 30,最多30位
5、當(dāng)前數(shù)字一定是0 或 1,判斷,誰(shuí)合適當(dāng)前位就填誰(shuí)

bool x = jisuan(0, i), y = jisuan(1, i); // 先分別處理出該位填 0 的結(jié)果和該位填 1 的結(jié)果 if (m >> i && x < y) // 判斷是否超過(guò)最大值,如果 m 右移 i 位仍不為 0,該位填 1 比該位填 0 更優(yōu),就填1 //如果填1不必0更優(yōu),那么為了讓剩下能填的數(shù)更大,在該位填 0 {sum |= y << i;m -= 1 << i; // 填完后讓 m 減去該位填 1 的結(jié)果,這樣在后面填數(shù)的時(shí)候只用考慮是否大于 m 就可以了 } else sum |= x << i; // 該位只能填 0

完整代碼:

#include <iostream> #include <vector> #include <algorithm> #include <cmath> #include <cstring> #include <cstdio> #include <iomanip>using namespace std; typedef long long ull; ull n,m,k,c,sum=0,x; int t[100005]; // t 存輸入的 n 個(gè)數(shù) string op[100005]; // op 存 n 個(gè)數(shù)對(duì)應(yīng)的操作 bool jisuan(bool x, int j) // jisuan 用于計(jì)算 x 經(jīng)過(guò)所有數(shù)的第 j 位操作后所得到的結(jié)果 {for (int i = 0; i < n; i ++ ) // 當(dāng)前數(shù)字,遍歷n道門(mén)if (op[i] == "OR") x |= t[i] >> j & 1;else if (op[i] == "XOR") x ^= t[i] >> j & 1;else x &= t[i] >> j & 1;return x; } int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n>>m;for(int i=0; i<n; i++){cin>>op[i]>>t[i];}for(int i=29; i>=0; i--){bool x = jisuan(0, i), y = jisuan(1, i); if (m >> i && x<y) {sum |= y << i; m -= 1 << i; }else sum |= x << i; }cout<<sum<<endl;return 0; }

下面是一個(gè)更技巧的寫(xiě)法,真神奇
利用:
0的二進(jìn)制是: 00000000…………
-1的二進(jìn)制是:1111111111…………
只用0和-1進(jìn)行位運(yùn)算,就可以得到任何一位的任何情況進(jìn)行位運(yùn)算的結(jié)果

我們本來(lái)是循環(huán)一次就判斷一次n道門(mén)后,0和1誰(shuí)更合適
令a=0,b=-1, 把函數(shù)省掉,不用每次都判斷當(dāng)前這位數(shù)經(jīng)過(guò)n道門(mén)之后的結(jié)果,在輸入的時(shí)候直接保存了每一位數(shù)的結(jié)果

#include <iostream> #include <vector> #include <algorithm> #include <cmath> #include <cstring> #include <cstdio> #include <iomanip> #include <queue> #include <list> #include <stack>using namespace std; typedef long long ull; ull n,t,m,k,c,sum=0,x; const int M=1<<29; string s;int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int a=0,b=-1;cin>>n>>m;for(int i=1;i<=n;i++){cin>>s>>x;if(s=="AND") a&=x,b&=x;else if(s=="OR") a|=x,b|=x;else a^=x,b^=x;}k=0;for(int i=29;i>=0;i--){bool x=a>>i&1,y=b>>i&1;if(m>>i && x<y) //填1{sum |= 1<<i;m -= 1 << i;}else sum |= x<<i; //填0}cout<<sum<<endl;return 0; }

總結(jié)

以上是生活随笔為你收集整理的起床困难综合征(位运算)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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