【CF949E】Binary Cards
阿新 • • 發佈:2021-10-11
題目
題目連結:https://codeforces.com/problemset/problem/949/E
給出 \(n\) 個需要表示的數,你需要用最少的 \(2^k\) 或 \(-2^k\),使得能拼出所有需要表示的數。輸出方案。
\(n,|a_i|\leq 10^5\)。
思路
首先 \(2^k\) 與 \(-2^k\) 中最多選一個。因為選兩個 \(2^k\) 不如選 \(2^k\) 和 \(2^{k+1}\);選 \(2^k\) 和 \(-2^k\) 不如選 \(2^{k+1}\) 和 \(-2^k\)。
從低位往高位依次考慮。如果這一位中存在二進位制下為 \(1\) 的數,那麼必然會選,否則必然不選。
直接列舉所有情況跑是 \(O(nA)\)
那麼每次操作完後都去重一次就好了。
時間複雜度 \(O(n\log A)\)。
程式碼
#include <bits/stdc++.h> using namespace std; const int N=100010,LG=18; int n,m,a[LG+1][N],b[LG+1],c[LG+1]; void solve(int dep,int n,int cnt) { if (cnt>=m || dep>LG) return; if (n==1 && !a[dep][1]) { memcpy(b,c,sizeof(b)); m=cnt; return; } bool flag=0; for (int i=1;i<=n;i++) if (a[dep][i]&1) { flag=1; break; } if (!flag) { for (int i=1;i<=n;i++) a[dep+1][i]=(a[dep][i]>>1); solve(dep+1,n,cnt); } else { for (int i=1;i<=n;i++) a[dep+1][i]=((a[dep][i]-(a[dep][i]&1))>>1); int n1=unique(a[dep+1]+1,a[dep+1]+1+n)-a[dep+1]-1; c[cnt+1]=(1<<dep); solve(dep+1,n1,cnt+1); for (int i=1;i<=n;i++) a[dep+1][i]=((a[dep][i]+(a[dep][i]&1))>>1); n1=unique(a[dep+1]+1,a[dep+1]+1+n)-a[dep+1]-1; c[cnt+1]=-(1<<dep); solve(dep+1,n1,cnt+1); } } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[0][i]); sort(a[0]+1,a[0]+1+n); n=unique(a[0]+1,a[0]+1+n)-a[0]-1; m=1e9; solve(0,n,0); cout<<m<<"\n"; for (int i=1;i<=m;i++) cout<<b[i]<<" "; return 0; }