#line 1 "d.cpp" #include #line 3 "d.cpp" using namespace std; using ll=long long; const ll ILL=2167167167167167167; const int INF=2100000000; #define rep(i,a,b) for (int i=(int)(a);i<(int)(b);i++) #define all(p) p.begin(),p.end() template using pq_ = priority_queue, greater>; template int LB(vector &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();} template int UB(vector &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();} template bool chmin(T &a,T b){if(b bool chmax(T &a,T b){if(a void So(vector &v) {sort(v.begin(),v.end());} template void Sore(vector &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});} bool yneos(bool a,bool upp=false){if(a){cout<<(upp?"YES\n":"Yes\n");}else{cout<<(upp?"NO\n":"No\n");}return a;} template void vec_out(vector &p,int ty=0){ if(ty==2){cout<<'{';for(int i=0;i<(int)p.size();i++){if(i){cout<<",";}cout<<'"'< T vec_min(vector &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmin(ans,x);return ans;} template T vec_max(vector &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmax(ans,x);return ans;} template T vec_sum(vector &a){T ans=T(0);for(auto &x:a) ans+=x;return ans;} int pop_count(long long a){int res=0;while(a){res+=(int)(a&1),a>>=1;}return res;} template T square(T a){return a * a;} #include using mint = atcoder::modint998244353; #line 4 "/Users/Shared/po167_library/math/Bitwise_Convolution.hpp" namespace po167{ //https://kazuma8128.hatenablog.com/entry/2018/05/31/144519 template void and_fwt(std::vector &f){ int n = f.size(); for (int i = 1; i < n; i <<= 1){ for (int j = 0; j < n; j++){ if ((j & i) == 0){ f[j] = f[j] + f[j | i]; } } } } template void and_ifwt(std::vector &f){ int n = f.size(); for (int i = 1; i < n; i <<= 1){ for (int j = 0; j < n; j++){ if ((j & i) == 0){ f[j] = f[j] - f[j | i]; } } } } template std::vector and_convolution(std::vector p, std::vector q){ int n = p.size(); assert(n == (int)q.size()); and_fwt(p), and_fwt(q); for (int i = 0; i < n; i++) p[i] = p[i] * q[i]; and_ifwt(p); return p; } template void or_fwt(std::vector &f){ int n = f.size(); for (int i = 1; i < n; i <<= 1){ for (int j = 0; j < n; j++){ if (j & i){ f[j] = f[j] + f[j ^ i]; } } } } template void or_ifwt(std::vector &f){ int n = f.size(); for (int i = 1; i < n; i <<= 1){ for (int j = 0; j < n; j++){ if (j & i){ f[j] = f[j] - f[j ^ i]; } } } } template std::vector or_convolution(std::vector p, std::vector q){ int n = p.size(); assert(n == (int)q.size()); or_fwt(p), or_fwt(q); for (int i = 0; i < n; i++) p[i] = p[i] * q[i]; or_ifwt(p); return p; } template void xor_fwt(std::vector &f){ int n = f.size(); for (int i = 1; i < n; i <<= 1){ for (int j = 0; j < n; j++){ if (j & i){ T x = f[j ^ i], y = f[j]; f[j ^ i] = x + y; f[j] = x - y; } } } } template std::vector xor_convolution(std::vector p, std::vector q){ int n = p.size(); assert(n == (int)q.size()); xor_fwt(p), xor_fwt(q); for (int i = 0; i < n; i++) p[i] = p[i] * q[i]; xor_fwt(p); T inv = (T)(1) / (T)(n); for (int i = 0; i < n; i++) p[i] = p[i] * inv; return p; } }; #line 29 "d.cpp" void solve(); // DEAR MYSTERIES / TOMOO int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t = 1; // cin >> t; rep(i, 0, t) solve(); } void solve(){ int N; cin >> N; vector A(N); rep(i, 0, N) cin >> A[i]; int D = 18; vector C(1 << D); rep(i, 0, N) { C[A[i]] += 1; } mint ans = 0; { auto tmp = po167::xor_convolution(C, C); mint a = 0, c = 0; rep(i, 0, 1 << D) { ans += c * tmp[i] * i; ans -= a * tmp[i]; c += tmp[i]; a += tmp[i] * i; } // i = j or k = l rep(i, 0, 1 << D) { ans -= tmp[i] * (mint(i)) * N; } // i = j = k rep(i, 0, 1 << D) { ans += tmp[i] * (mint(i)) * 4; } ans *= 2; } // cout << ans.val() << " "; // i = k とか vector p(2, vector(D, vector(D + 1))); rep(i, 0, N) { rep(j, 0, D) { int a = (A[i] & (1 << j) ? 1 : 0); p[a][j][D] += 1; rep(k, 0, D) if (A[i] & (1 << k)) { p[a][j][k] += 1; } } } auto f = [&](auto self, int d, vector B) -> void { if (d == -1 || B.empty()) return; vector> v(2); for (auto x : B) v[min(1, x & (1 << d))].push_back(x); rep(j, 0, 2) { self(self, d - 1, v[j]); for (auto x : v[j]) rep(k, 0, 2) { mint tmp = 0; // d けためが k のものを xor する for (int i = D - 1; i >= 0; i--) { tmp *= 2; if (x & (1 << i)) { tmp += p[k][d][D] - p[k][d][i]; } else { tmp += p[k][d][i]; } } // 大きいか小さいか if (k == j) tmp *= -1; // index の選び方 tmp *= 4; // 相手となるものの個数 tmp *= v[j ^ 1].size(); // 順序 tmp *= 2; // cout << d << " " << j << " " << k << " " << x << " " << tmp.val() << " " << (-tmp).val() << "\n"; ans -= tmp; } } }; f(f, D - 1, A); cout << ans.val() << "\n"; if (false) { auto f = [&](int i, int j, int k, int l) -> int { return abs((A[i] ^ A[j]) - (A[k] ^ A[l])); }; ans = 0; rep(i, 0, N) rep(j, 0, N) rep(k, 0, N) rep(l, 0, N) { ans += f(i, j, k, l); } rep(i, 0, N) rep(j, 0, N) rep(k, 0, N) { ans -= f(i, i, j, k) * 2; ans -= f(i, j, i, k) * 4; } rep(i, 0, N) rep(j, 0, N) { ans += f(i, i, i, j) * 8; } } } /* * i, j を選ばず、A[k] ^ A[l] > A[i] ^ A[j] となるものは何通りある? * A[k] ^ A[l] = A[i] ^ A[j] となるものは何通りある? * シンプルに A[k] ^ A[l] = x となるものの個数を C[x] とする * A[i] != A[j] のとき、 * C[A[i] ^ A[j]] + 1 - freq[A[i]] - freq[A[j]] * まとめて計算することはできそう * A[k] ^ A[l] > A[i] ^ A[j] であるものの個数も大体わかる? * 包除原理を考えるか * 条件なし -> easy * i = j -> まあいけるやろ * i = j = k とかもまあ * i = k のみとかがやばい * A[j], A[l] のアレを考えると良い */