由于异或运算按位独立,我们可以用一个经典的trick:拆位 计算该位上的贡献,再把每一位的贡献加起来,得到答案。

对于第 i 位(i = 0 ~ 30),我们只关心每个顶点的这一位是 0 还是 1。

  • a[j] = (v[j] >> i) & 1 取出顶点 j 的第 i 位值(0 或 1)。

  • 因为图是无向的,且路径长度固定为 2,我们可以枚举每一个中间顶点 v,然后去看它的邻居uw

对固定的中间顶点 v

设它的邻居集合中:

  • cnt0 = 邻居中第 i 位为 0 的个数
  • cnt1 = 邻居中第 i 位为 1 的个数
情况 1:a[v] == 0(中间顶点第 i 位为 0)

要使三个顶点有奇数个 1,则邻居中必须有恰好一个 1

  • 一个邻居为 1,另一个为 0 → 无序对数量 = cnt0 * cnt1
情况 2:a[v] == 1(中间顶点第 i 位为 1)

要使奇数个 1,则邻居中必须有 2 个 0 或者 2 个 1。

  • 两个邻居都是 0:方案数 = cnt0 * (cnt0 - 1) / 2
  • 两个邻居都是 1:方案数 = cnt1 * (cnt1 - 1) / 2
  • 总方案数 = 两者相加。
接着
  • 设第 i 位上得到的合法路径总数为 cnt
  • 这一位对最终答案的贡献 = cnt * 2^i
  • 记得取模

时间复杂度

代码如下:

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define debug(x) cerr << #x << ": " << x << '\n';
// #define int long long
#define ctz __builtin_ctzll         // 返回二进制表示中末尾连续0的个数
#define clz __builtin_clzll         // 返回二进驻表示中先导0的个数
#define count1 __builtin_popcountll // 返回二进制表示中1的个数
// 上面仨不是ll的时候记得调整
#define lowbit(x) (x & -x)
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int N = 1e5 + 100;
const double EPS = 1e-8;
// const ll MOD = 1e9 + 7;
const ll MOD = 998244353;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll dir[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
ll dirr[8][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}, {1, 1}, {1, -1}, {-1, -1}, {-1, 1}};

void LiangBaiKai()
{

}

void Aiden()
{
    ll n, m;
    cin >> n >> m;
    vector<ll> v(n + 1);
    for (ll i = 1; i <= n; i++)
        cin >> v[i];
    // 邻接表建图
    vector g(n + 1, vector<ll>());
    for (ll i = 1; i <= m; i++)
    {
        ll x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    ll ans = 0; // 最终答案
  
    // 枚举每一位(0 ~ 30,因为 a_i ≤ 1e9 < 2^30)
    for (ll i = 0; i <= 30; i++)
    {
        // a[j] 存储第 j 个顶点在当前位上的值(0 或 1)
        vector<ll> a(n + 1);
        for (ll j = 1; j <= n; j++)
            a[j] = (v[j] >> i) & 1;
        ll cnt = 0; // 当前位上异或结果为 1 的路径总数
      
        // 枚举每个顶点作为中间顶点 v
        for (ll j = 1; j <= n; j++)
        {
            ll cnt0 = 0, cnt1 = 0; // 统计其邻居中当前位为 0 和 1 的个数
            for (auto e : g[j])
            {
                if (a[e] == 0)
                    cnt0++;
                else
                    cnt1++;
            }
            // 根据中心顶点的当前位值,计算合法邻居对的数量
            if (a[j] == 0)
                cnt += cnt0 * cnt1; // 中心为 0 时,需要邻居一个0和一个1
            else
                cnt += cnt0 * (cnt0 - 1) / 2 + cnt1 * (cnt1 - 1) / 2; // 中心为 1 时,需要邻居两个0或两个1
        }

        cnt %= MOD; // 取模防止溢出
        ans = (ans + cnt * (1ll << i) % MOD) % MOD; // 贡献 = 路径数 * (1 << i),累加到答案
    }

    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    LiangBaiKai();
    int _ = 1;
    //cin >> _;
    while (_--)
        Aiden();
    return 0;
}

/*
                                                @@@@@@
                                                @@@@@@@@@@
                                                @@@@@@@@@@@@@
                                               @@@@@@@@@@@@@@@
                                               @@@@@@@@@@@
                                              @@@@
                                              @
                                  @@@@@@@@@@ @@ @@@@@@@@@@@@
                              @@@@@          @              @@@@@
                          @@@                @                   @@@
                       @@@                  @@                      @@@
                     @@                                                @@@
                   @@                                                     @@
                 @@                                                        @@
                @@                                                           @@
               @                                                              @@
              @          @@@@@@@@                                              @@
             @     @@@  @@@@@@@@@                                               @
            @@  @@@@@@@ @@@@@@@@  @@@@@@                                         @
            @  @@@@@@@@@@@@@@@@@@@@@@@@@@                                        @@
            @ @@@@@@@@@@@      @@@@@@@@@@@                                        @
             @@@@@@@@@@@@@   @@@@@@@@@@@@@@  @                             @@@@@@ @
            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@    @@      @@@@@@         @@@        @
           @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@      @@@         @@@  @@@          @
          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                  @@@@@
         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@     @@@
        @@@@@@       @@@@@@@@@@  @@@@@@@@@@@@@@                                        @@
       @@@@@  @@@@@@@ @@@@@@   @@   @@@@@@@@@@@                                     @@@
       @@@@@ @@@@@@@@  @@@@  @@@@@@@ @@@@@@@@@@@                                 @@
      @@@@@@  @@@@@@@ @@@@@  @@@@@@@  @@@@@@@@@@@@                            @@@@@@@
      @@@@@@@    @   @@@@@@  @@@@@@@ @@@@@@@@@@@@@@@@                      @@@@@@@@@@@
      @@@@@@@@@@@@@@@@@@@@@@@   @   @@@@@@@@@@@@@@@@@@@                @@@@@@@@@@@@@@@@@
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@          @@@@@@@@@@@@@@@@@@@@@
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@ @@@@@@@@@@
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@              @@@@@@@@@@
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@               @       @   @  @@@@@@@@@@@@
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@        @ @@@@@ @        @@@@   @   @@@@@@@@@@
        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@    @@      @@      @@    @@@   @@@@@   @@@@@@@@@@
         @@@@@@@        @@@@@@@@@@@@@@         @@@@@@         @@@@@              @ @@@@@@@@
          @@@@@@        @@@@@@@@@@@                                             @  @@@@@@@@
           @@@@         @@@@@@@@                                              @@  @@@@@@@
              @@                                                              @@    @@@@@
               @@@                                                          @@
                  @@@                                                    @@@
                     @@@@@@@@@@@@                            @@@@@@@@@@@
                                @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*/