Codeforces 949E Binary Cards
阿新 • • 發佈:2018-07-15
contest 復雜 ons break 是我 ++ n) include ORC 或者 \(2^k\) 把含有這一位的數都給去掉,然後再把所有的數除以 \(2\)
對於第二種情況我們直接搜索一下就好了
Description
給出一個長度為 \(n\) 的數組,求使得用最少數量的 \(2^k\) 或 \(-2^k\) 的數,使得數組中的每一個元素都可以被你選出的 \(2\) 的次冪表示
題面
Solution
註意到兩個性質:
1.一個數不會用兩次,舉個例子:用兩個 \(2\),不如用 \(2,4\) 範圍廣
2.一個數不會既用 \(2^k\) 又用 \(-2^k\),顯然用 \(-2^k,2^{k+1}\) 或者 \(2^k,-2^{k+1}\) 更優
這樣就可以依次考慮每一位了:
如果所有的數都不含有這一位,那麽就直接把所有的數除以 \(2\)
如果存在數含有這一位,那麽用 \(-2^k\)
對於第二種情況我們直接搜索一下就好了
這樣復雜度有些問題,但是我們把數去重之後,第 \(k\) 層的數就最多只有 \(\frac{max(A[i])}{2^{k}}\)
復雜度就變成了分治的復雜度了
#include <bits/stdc++.h> using namespace std; const int N=100010; int a[N],b[21][N],top=0,st[N],ans[N],anslen=N; inline void dfs(int t,int n){ if(t>20 || top>=anslen)return ; if(n==1 && !b[t][1]){ if(top<anslen){ anslen=top; for(int i=1;i<=top;i++)ans[i]=st[i]; } return ; } bool flag=1; for(int i=1;i<=n;i++)if(b[t][i]&1){flag=0;break;} if(flag){ for(int i=1;i<=n;i++)b[t+1][i]=b[t][i]>>1; n=unique(b[t+1]+1,b[t+1]+n+1)-b[t+1]-1; dfs(t+1,n); return ; } for(int w=-1;w<=1;w+=2){ for(int i=1;i<=n;i++) if(b[t][i]&1)b[t+1][i]=(b[t][i]+w)>>1; else b[t+1][i]=b[t][i]>>1; st[++top]=-w*(1<<t); int tmp=unique(b[t+1]+1,b[t+1]+n+1)-b[t+1]-1; dfs(t+1,tmp); top--; } } int main() { freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); int n; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); sort(a+1,a+n+1); n=unique(a+1,a+n+1)-a-1; for(int i=1;i<=n;i++)b[0][i]=a[i]; dfs(0,n); printf("%d\n",anslen); for(int i=1;i<=anslen;i++)printf("%d ",ans[i]); return 0; }
Codeforces 949E Binary Cards