起床困難綜合癥 NOI2014
阿新 • • 發佈:2018-10-01
fin 二進制 isp can 綜合癥 sin 運算 opened 最大值
這道題簡單題意就是從0到m選一個數,進行n此操作,使得操作完的數最大。
這道題可以很暴力想到O(nm)的做法,枚舉每個0到m的數進行n次操作後的值進行取最大值
但數據範圍明顯過不去,所以我們要優化一下
首先這些操作都是位運算,是在二進制下對每一位的操作。
因為二進制下每一位都相對獨立,並且每一位只有0和1兩種情況,所以我們從高位到低位枚舉0或1(保證最優解最大),找出能得到最優解的x(0<=x<=m)
對於每一位枚舉的0/1共有4種情況,
(ans為記錄最優解大小,kkk記錄x的大小)
當枚舉為0時,
1.操作後為0時不用管它
2.操作後為1時ans累加
當枚舉為1時
1.操作後為0時不管
2.操作後為1時且kkk加上這個二進制當前位的大小小於m時 kkk和ans累加。
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define ll long long using namespace std; const int maxn=1000000+101010; inline int read(){ int x=0,f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar())ifView Code(ch==‘-‘)f=-1; for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-‘0‘; return x*f; } int n,m; struct wzq{ int x,y; }a[maxn]; int main(){ n=read();m=read(); int kk=0,kkk=0; for(int i=1;i<=n;i++){ char b[30]; int q; scanf("%s%d",b,&a[i].y);if(b[0]==‘A‘)a[i].x=1; if(b[0]==‘O‘)a[i].x=2; if(b[0]==‘X‘)a[i].x=3; } for(int i=30;i>=0;i--){ int t=1<<i,k=0; for(int j=1;j<=n;j++){ if(a[j].x==1)t=t&a[j].y,k=k&a[j].y; if(a[j].x==2)t=t|a[j].y,k=k|a[j].y; if(a[j].x==3)t=t^a[j].y,k=k^a[j].y; kkk+=1<<i; } } printf("%d",kk); return 0; } /* 3 10 AND 5 OR 6 XOR 7 */
起床困難綜合癥 NOI2014