度度熊专门研究过“动态传递闭包问题”,他有一万种让大家爆蛋的方法;但此刻,他只想出一道简简单单的题——至繁,归于至简。
度度熊有一张n个点m条边的无向图,第iii个点的点权为viv_ivi。
如果图上存在一条路径使得点iii可以走到点jjj,则称i,ji,ji,j是带劲的,记f(i,j)=1f(i,j)=1f(i,j)=1;否则f(i,j)=0f(i,j)=0f(i,j)=0。显然有f(i,j)=f(j,i)f(i,j) = f(j,i)f(i,j)=f(j,i)。
度度熊想知道求出: ∑i=1n−1∑j=i+1nf(i,j)×max(vi,vj)×(vi&vj)\sum_{i=1}^{n-1} \sum_{j=i+1}^{n} f(i,j) \times \max(v_i, v_j) \times (v_i \& v_j)∑i=1n−1∑j=i+1nf(i,j)×max(vi,vj)×(vi&vj)
其中&\&&是C++中的and位运算符,如1&3=1, 2&3=2。
请将答案对109+710^9+7109+7取模后输出。
Input
第一行一个数,表示数据组数TTT。
每组数据第一行两个整数n,mn,mn,m;第二行nnn个数表示viv_ivi;接下来mmm行,每行两个数u,vu,vu,v,表示点uuu和点vvv之间有一条无向边。可能有重边或自环。
数据组数T=50,满足:
- 1≤n,m≤1000001 \le n,m \le 1000001≤n,m≤100000
- 1≤vi≤1091 \le v_i \le 10^91≤vi≤109。
其中90%的数据满足n,m≤1000n,m \le 1000n,m≤1000。
Output
每组数据输出一行,每行仅包含一个数,表示带劲的and和。
Sample Input
1
5 5
3 9 4 8 9
2 1
1 3
2 1
1 2
5 2
Sample Output
99
#pragma GCC optimize(2) #include<stdio.h> #include<algorithm> #include<string.h> #include<queue> using namespace std; const int maxn = 1e5 + 10; const int inf = 0x3f3f3f3f; const int MOD = 1e9 + 7; typedef long long ll; int t, n, tot, pos, m; int f[maxn]; int a[maxn]; vector<int>vec[maxn]; void init(int n) { for (int i = 0; i <= n; i++) { f[i] = i; } return; } int find(int x) { if (x == f[x]) { return x; } else { return f[x] = find(f[x]); } } void merge(int u, int v) { int x = find(u); int y = find(v); if (x == y) { return; } f[x] = y; } int main() { //freopen("C://input.txt", "r", stdin); int t; scanf("%d", &t); while (t--) { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), f[i] = i; for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); merge(u, v); } for (int i = 1; i <= n; i++) vec[i].clear(); for (int i = 1; i <= n; i++) { vec[find(i)].push_back(a[i]); } ll ans = 0; for (int i = 1; i <= n; i++) { sort(vec[i].begin(), vec[i].end()); ll op[35] = { 0 }; for (int j = 0; j < vec[i].size(); j++) { int pos = vec[i][j]; for (int k = 0; k < 32 && pos; k++) //安位拆分 { if (pos & 1) { op[k]++; } pos >>= 1; } } for (int j = vec[i].size() - 1; j > 0; j--) { int pos = vec[i][j]; for (int k = 0; k < 32 && pos; k++) { if (pos & 1) { op[k]--; ans = (ans + (1LL << k) % MOD * op[k] % MOD * vec[i][j] % MOD) % MOD; } pos >>= 1; } } } printf("%I64d\n", ans); } return 0; }