打卡信奥刷题(1792)用C++实现信奥 P8826 [传智杯 #3 初赛] 游戏(征集数据)

P8826 [传智杯 #3 初赛] 游戏(征集数据)

题目描述

清蒸鱼是一个从未被击败的炽蓝仙野游戏者。有一天他遇到了这么一个游戏:

给定一个长度为 nnn 的数组 aaa。同时定义 count(x)count(x)count(x)xxx 在二进制下的 111 的个数。

现在清蒸鱼每次可以进行如下两种操作:

  • 选择两个数 ai,aja_i, a_jai,aj,并且必须满足 count(aixor⁡aj)=1count(a_i \operatorname{xor} a_j)=1count(aixoraj)=1,将它们中的任意一个从数组中消去,代价为 C1C_1C1

  • 选择两个数 ai,aja_i, a_jai,aj,并且必须满足 count(aixor⁡aj)>1count(a_i \operatorname{xor} a_j) > 1count(aixoraj)>1,将它们中的任意一个从数组中消去,代价为 C2C_2C2

现在你想知道,最少付出多少的代价,能让这个数组被消到只剩一个数。

输入格式

第一行一个整数 nnn,表示数组大小。
第二行两个整数 C1,C2C_1, C_2C1,C2,意义如题所示。
第三行共 nnn 个整数,描述了数组 aaa

输出格式

一行一个整数,表示最小代价。

输入输出样例 #1

输入 #1

4
5 10
1 2 3 4

输出 #1

20

说明/提示

对于 20%20\%20% 的数据,满足 n=10n = 10n=10
对于另外 20%20\%20% 的数据,满足 aaa 中的元素为一个 [1,n][1, n][1,n] 的排列;
对于 100%100\%100% 的数据,满足 1≤n≤1041 \leq n \leq {10}^41n1041≤C1,C2,a≤1091\le C_1, C_2, a \le {10}^91C1,C2,a109aaa 中的元素互不相同。

C++实现

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e4+5;
int n,c1,c2,a[N],f[N],ans;
int getf(int u){
	if(f[u]==u)return u;
	return f[u]=getf(f[u]);
}
int calc(int x){
	return x&(-x);
} 
void merge(int x,int y){
	x=getf(x),y=getf(y);
	if(x==y)return;f[x]=y,ans++;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin >> n >> c1 >> c2;
	for(int i =1;i <= n;i++)cin >> a[i],f[i]=i;
	for(int i = 1;i <= n;i++){
		for(int j = i+1;j <= n;j++){
			int flag=0,val=(a[i]^a[j]);
			if((val||n<=10)&&calc(val)==val)flag=1;
			if(c1<c2&&flag)merge(i,j);
			else if(c1>c2&&!flag)merge(i,j);
		}
	}if(c1>c2)swap(c1,c2);
	cout << c1*ans+(n-1-ans)*c2;
	return 0;
}

在这里插入图片描述

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值