传送门 题意就是给你n个数,然后和一个有无限个点组成的图,如果图中 a b s ( i − j ) abs(i-j) abs(i−j)在这n个数中,则可以建立这条边。 要求最小删去多少个给定的数,使得该图是二分图。 二分图有一个最基本的性质就是不存在奇数环。 考虑如果存在环,从一个点x开始再回到x,如果边数不为奇数,
那么现有的数都要满足一个性质: 即二进制上的最低位(最小的那位)要相同,如此可保证不存在奇数环。遍历一遍找出每个数的最低位,然后找到计数最多的那一个二进制位,不对应-该二进制位-的都删去即可。
#include<bits/stdc++.h> using namespace std; int n; #define MAXN 205000 #define ll long long ll a[MAXN]; int cnt[MAXN]; int vis[MAXN]; ll step[65]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",a+i); step[0]=1; for(int i=1;i<=60;i++) step[i]=1ll<<i; for(int i=1;i<=n;i++) { ll x = a[i] & (-a[i]); for(int j=0;j<=60;j++) if(x==step[j]) { cnt[j]++; vis[i]=j; } } int ans=0; for(int i=1;i<=60;i++) if(cnt[i]>cnt[ans])ans=i; vector<ll>res; for(int i=1;i<=n;i++) if(vis[i]!=ans)res.push_back(a[i]); cout<<res.size()<<endl; for(int i=0;i<res.size();i++) { if(i)putchar(' '); printf("%lld",res[i]); } }