P9619 生成树

题目描述

现给定一个无向完全图 G(V,E) 和一个长度为∣V∣ 的权值数组 a.ai​ 表示编号为 i 的节点的权值.

定义一条边 e(u,v) 的边值为 val(e),满足val(e)=au​⊕av​,也就是边连接的两个节点的权值的异或和;定义 G 的一个生成树 T(V,Et​) 的权值为 Val(T),满足)Val(T)=∑e∈Et​​val(e),也就是树上边的边权和.

您需要求出∑T​Val(T).即 G 中所有不同生成树的权值的和.

我们认为两棵生成树是不同的,当且仅当两棵树的边集 Et​ 不完全相同,即至少存在一条边,满足其仅属于两棵生成树中的其中一棵.

输入格式

包括两行.

第一行是一个整数 n,表示 ∣V∣,即节点个数.

第二行是 n 个整数,依次为a1​∼an​.

输出格式

一行一个整数.表示你的答案对 998244353998244353 取模.

输入输出样例

输入 #1复制

3
1 2 3

输出 #1复制

12

输入 #2复制

6
1 1 4 5 1 4

输出 #2复制

19008

输入 #3复制

10
1 1 4 5 1 4 1 9 1 9

输出 #3复制

567022588

说明/提示

样例 #1 说明:

考虑一共存在三个生成树 {1−2−3},{1−3−2},{3−1−2}{1−2−3},{1−3−2},{3−1−2}.

它们的权值分别为 (1⊕2)+(2⊕3)=4,(1⊕3)+(3⊕2)=3,(3⊕1)+(1⊕2)=5(1⊕2)+(2⊕3)=4,(1⊕3)+(3⊕2)=3,(3⊕1)+(1⊕2)=5.

有 4+3+5=124+3+5=12.

数据点约束

保证对于所有数据,1≤n≤106,0≤ai​≤109.

测试点编号数据范围特殊性质
11所有 ��ai​ 相等
2∼52∼5�≤4n≤4
6∼106∼10�≤300n≤300
11∼1211∼12�≤5×104n≤5×104��=[�=1]ai​=[i=1]
11∼1511∼15�≤5×104n≤5×104
16∼2016∼20
#include<bits/stdc++.h>
#define ll long long
#define mod 998244353

using namespace std;
ll n,cnt[105],a[1000005],sum=0;
int main(){
	scanf("%lld",&n);
	for(ll i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		for(ll j=0;j<=30;j++) cnt[j]+=(((1<<j)&a[i])?1:0);
	}
	for(ll i=1;i<=n;i++){
		for(ll j=0;j<=30;j++){
			if((1<<j)&a[i]){
				sum+=(n-cnt[j])*(1<<j);
				sum%=mod;
			}//如果j和a[i]奇偶性相同,需要用n减
			else{
				sum+=cnt[j]*(1<<j);
				sum%=mod;
			}//反之不用n减,直接乘
		}
	}
	if(n>=3) sum=sum*qpow(n,n-3)%mod;//每条边计算的次数为mod(n,n-3)
	else sum=sum%mod;//只有1或2条边,取模即可
	printf("%lld",sum);//输出
	return 0;
}

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值