#include <bits/stdc++.h> // Thư viện tổng hợp, chứa vector, iostream, etc.
using namespace std;
// Hằng số modulo. Kết quả cuối cùng phải chia lấy dư cho số này.
const int MOD = 1e9 + 7;
// ======================================================================
// "CỖ MÁY" FWHT - Trái tim của thuật toán
// Hàm này thực hiện cả biến đổi xuôi và ngược.
// a: Mảng cần biến đổi (sẽ bị thay đổi trực tiếp).
// inverse: cờ điều khiển.
// - false: Biến đổi xuôi (FWHT xuôi), dùng phép cộng.
// - true: Biến đổi ngược (FWHT ngược), dùng phép trừ.
// ======================================================================
void fwht_or(vector<long long>& a, bool inverse) {
int n = a.size(); // Kích thước mảng, luôn là lũy thừa của 2.
// len: Kích thước của "một nửa nhóm" đang xét. Bắt đầu từ 1, 2, 4, ...
for (int len = 1; len < n; len <<= 1) { // len <<= 1 tương đương len = len * 2
// i: Điểm bắt đầu của các "nhóm lớn" (kích thước 2*len).
// Nó nhảy qua từng nhóm lớn một.
for (int i = 0; i < n; i += 2 * len) {
// j: Vị trí tương ứng trong mỗi nửa nhóm.
// Để ghép cặp phần tử thứ j của nửa đầu với phần tử thứ j của nửa sau.
for (int j = 0; j < len; j++) {
// u: Phần tử ở nửa đầu của nhóm.
long long u = a[i + j];
// v: Phần tử tương ứng ở nửa sau của nhóm.
long long v = a[i + len + j];
// Logic biến đổi cốt lõi
if (!inverse) {
// Biến đổi xuôi: a' = a + b
// Nửa sau sẽ cộng dồn thông tin từ nửa đầu.
a[i + len + j] = (v + u) % MOD;
} else {
// Biến đổi ngược: a = a' - b
// Nửa sau sẽ loại bỏ thông tin đã được cộng vào ở bước xuôi.
a[i + len + j] = (v - u + MOD) % MOD; // +MOD để đảm bảo kết quả không âm
}
}
}
}
}
int main() {
// Tối ưu hóa tốc độ nhập xuất
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
// ======================================================================
// BƯỚC 0: ĐỌC DỮ LIỆU VÀ CHUẨN BỊ
// ======================================================================
int n;
cin >> n; // Đọc kích thước mảng gốc
// FWHT yêu cầu kích thước mảng phải là lũy thừa của 2.
// Tìm N là lũy thừa của 2 nhỏ nhất >= n.
int N = 1;
while (N < n) {
N *= 2;
}
// Tạo vector `a` với kích thước N. Các phần tử thừa (từ n đến N-1)
// sẽ có giá trị 0, không ảnh hưởng đến tổng.
vector<long long> a(N, 0);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
// TRẠNG THÁI HIỆN TẠI: `a` chứa các giá trị gốc {a₀, a₁, ..., aₙ₋₁, 0, 0, ...}
// ======================================================================
// BƯỚC 1 & 2: KẾ HOẠCH & FWHT XUÔI
// Kế hoạch: Tính mảng C. Để làm vậy, ta biến đổi `a` sang "thế giới song song".
// ======================================================================
fwht_or(a, false); // Gọi "cỗ máy" ở chế độ xuôi.
// TRẠNG THÁI HIỆN TẠI: `a` đã bị biến đổi. Nó không còn chứa giá trị gốc.
// Giờ đây nó chứa mảng `hat_a`, với a[k] = tổng các a_gốc[i] mà i là submask của k.
// ======================================================================
// BƯỚC 3: PHÉP NHÂN "THẦN KỲ"
// Đây là "đường tắt" O(N) để thực hiện phép tích chập.
// ======================================================================
for (int i = 0; i < N; ++i) {
a[i] = (a[i] * a[i]) % MOD;
}
// TRẠNG THÁI HIỆN TẠI: `a` bây giờ chứa mảng `hat_C`.
// hat_C[k] = hat_a[k] * hat_a[k].
// Đây là mảng C nhưng vẫn đang ở "thế giới song song".
// ======================================================================
// BƯỚC 4: FWHT NGƯỢC
// Đưa kết quả từ "thế giới song song" trở về "thế giới thực".
// ======================================================================
fwht_or(a, true); // Gọi "cỗ máy" ở chế độ ngược.
// TRẠNG THÁI HIỆN TẠI: `a` bây giờ chứa mảng `C`.
// a[k] = C[k] = tổng của tất cả a_gốc[i] * a_gốc[j] mà i | j = k.
// Chúng ta đã thành công tính được mảng trung gian quan trọng nhất.
// ======================================================================
// BƯỚC 5: TÍNH TỔNG TIỀN TỐ ĐỂ RA KẾT QUẢ CUỐI CÙNG
// Từ mảng C, ta tính S(U) = C[0] + C[1] + ... + C[U].
// ======================================================================
vector<long long> result(n); // Vector để chứa n đáp án cuối cùng.
// S(0) chính là C[0] (tức là a[0] hiện tại).
if (n > 0) {
result[0] = a[0];
}
// Vòng lặp tính các S(U) còn lại.
// result[i] tương ứng với S(i).
// S(i) = S(i-1) + C[i]
for (int i = 1; i < n; ++i) {
result[i] = (result[i - 1] + a[i]) % MOD;
}
// TRẠNG THÁI HIỆN TẠI: `result` chứa các đáp án S(0), S(1), ..., S(n-1).
// ======================================================================
// IN KẾT QUẢ
// ======================================================================
for (int i = 0; i < n; ++i) {
cout << result[i] << (i == n - 1 ? "" : " ");
}
cout << endl;
return 0;
}