首先可以发现,如果有a,b,c三个点,且a向b和c连边,b向c连边,
那么此时a直接走到c一定比以b作为中间结点更优

开始将维护数组v[i],v[i]里面存了所有二进制第i位为1的数的编号
那么可以构造一个DAG,比如刚开始的时候枚举a[1]的所有的1位,然后直接把v[i]里面的所有点的最短路更新为1到它的距离。然后让新的点入优先队列。
维护一个优先队列让距离小的优先更新,而每个v[i]最多被访问一次,即每个点到1的最多距离最多只会被更新一次

#include <bits/stdc++.h>
#define N 100010
#define ll long long
//#define Re register
#define mo 998244353
#define squ(x) ((x)*(x))
#define db double
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define drep(i,r,l)for(int i=r;i>=l;--i)
#define pb push_back
using namespace std;

inline ll read() {
    ll x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-')f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    return x * f;
}
int a[N];
vector<int> v[34];
ll dis[N];
bool vis[34];
#define Pa pair<ll,int>
#define mp make_pair
priority_queue<Pa, vector<Pa>, greater<Pa> > q;
bool cmp(int i, int j) {
    return a[i] < a[j];
}
int main() {
    int n = read();
    rep(i, 1, n) {
        dis[i] = -1;
        a[i] = read();
        rep(p, 0, 30)if ((a[i] >> p) & 1)v[p].pb(i);
    }
    rep(p, 0, 30)sort(v[p].begin(), v[p].end(), cmp);
    dis[1] = 0;
    q.push(mp(a[1], 1));
    while (!q.empty()) {
        int u = q.top().second;
        q.pop();
        rep(p, 0, 30) {
            if ((a[u] >> p) & 1) {
                if (vis[p])continue;
                vis[p] = 1;
                for (int &x : v[p])
                {
                    if (dis[x] != -1)continue;
                    dis[x] = dis[u] + a[u] + a[x];
                    q.push(mp(dis[x] + a[x], x));
                }
            }
        }
    }
    rep(i, 1, n)printf("%lld ", dis[i]);
    return 0;
}