1. 程式人生 > >起床困難綜合癥 NOI2014

起床困難綜合癥 NOI2014

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())if
(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 */
View Code

起床困難綜合癥 NOI2014