題意:首先給你一個集合B,定義一個圖是由整數集合為定點,若i,j為整數,且 abs(i - j) 在集合 B 之中,那么圖中存在一條連接 i,j 的無向邊。問至少去掉 B 中多少個元素才能使這張圖為一個二分圖。
其實我不清楚這道題到底算不算數論,但肯定不是圖論,只用到了判定二分圖的基本方法:不存在奇環。
如何讓這個圖不存在奇環?
我們考慮起點為 0,如果 B 中存在整數 a, 那么 0 與 a 之間有一條邊,a 與 2 * a 之間也有一條邊,如果這時 B 中還存在着整數 2 * a,那么這時 0,a,2 * a 這三個點就形成了奇環。
考慮到這里,我們發現,如果我們已經選中了一個數 a,那么要不存在奇環,只有將 a / 2(a % 2 == 0) , a / 4(a % 4 == 0)…… ,a * 2 ,a * 4,…… 全部刪去。
但這樣思考卻很難求出答案,那就只有換一個思考方向,想一想如果選中了 a,那么哪些數可以保留,不難發現,只有和 a 同次數(不停的除以 2,直到無法除盡或等於 0 為止,這樣操作的次數)的數才能和 a 一起保留。因為這樣的話,這些數中就不會出現翻倍的關系。
那么代碼就很簡單了
#include <bits/stdc++.h> using namespace std; typedef long long LL; int n,num[100],cnt[200010]; LL a[200010]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); for(int i=1;i<=n;i++) { LL temp=a[i]; while(temp&&temp%2==0) { cnt[i]++; temp/=2; } num[cnt[i]]++; } int id=0; for(int i=1;i<=63;i++) if(num[i]>num[id]) id=i; printf("%d\n",n-num[id]); for(int i=1;i<=n;i++) if(cnt[i]!=id) printf("%lld ",a[i]); return 0; }