牛客練習賽23-C-托米的位運算(模擬)
阿新 • • 發佈:2019-01-31
題目描述
托米完成了1317的上一個任務,十分高興,可是考驗還沒有結束
說話間1317給了托米 n 個自然數 a1... an, 托米可以選出一些帶回家,但是他選出的數需要滿足一些條件
設托米選出來了k 個數 b1,b2... bk, 設這個數列 b 的給值為 b 中所有數按位與的結果,如果你能找到一個整除 b 的最大的 2v,(v≥ 0), 則設定 v 為這個數列的給價,如果不存在這樣的 v,則給價值為 -1, 1317 希望托米在最大化給價的情況下,最大化 k
輸入描述:
第一行輸入一個整數 n, 第二行輸入 a1...an
輸出描述:
第一行輸出最大的整數 k, 第二行輸出 k 個整數 b1... bk, 按原數列的相對順序輸出 (如果行末有額外空格可能會格式錯誤)
示例1
輸入
5
1 2 3 4 5
輸出
2
4 5
備註:
n≤ 10^5, a1... an < 2^31
題解:與的特點是某位為0,則只要添上這個數,最後相與的結果這一位一定是0,因此我們暴力數列的給價
從31到0,每次只有陣列中該位為1才可能對答案有貢獻,並且其他位一定不影響(如果最後答案成立的話)。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define ll long long ll n,a[100005],b[100005]; int main(void) { int k; scanf("%lld",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); for(int i=31;i>=0;i--) { k=0; ll ans=((1<<i)-1); for(int j=1;j<=n;j++) { if(a[j]&(1<<i)) ans=(ans&a[j]),b[++k]=a[j]; } if((ans&-ans)==(1<<i))//x&(-x)返回x與2^64的最大公約數 break; } printf("%d\n",k); for(int i=1;i<k;i++) printf("%lld ",b[i]); printf("%lld\n",b[k]); return 0; }