ARC146 部分题解

A
普及组题

// by Balloons
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Madoka"<<endl
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f, maxn=2e5+5;

int n;
pair<int,int> a[maxn];

int gt(int x){int t=0;while(x){++t;x/=10;}return t;}

int cmp(pair<int,int> a,pair<int,int> b){
	return a.first == b.first ? a.second > b.second : a.first > b.first;
}

signed main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i].second), a[i].first = gt(a[i].second);
	sort(a+1,a+n+1,cmp);
	if(a[1].first == a[3].first)
		for(int i=1;i<=3;i++){
			printf("%d",a[i].second); 
		}
	else{
		int t1 = a[1].second, t2 = a[2].second, t3 = a[3].second;
		LL p1 = t1*(LL)pow(10,gt(t3)+gt(t2)) + t2*(LL)pow(10,gt(t3))+t3;
		LL p2 = t1*(LL)pow(10,gt(t2)+gt(t3)) + t3*(LL)pow(10,gt(t2))+t2;
		LL p3 = t2*(LL)pow(10,gt(t3)+gt(t1)) + t1*(LL)pow(10,gt(t3))+t3;
		LL p4 = t2*(LL)pow(10,gt(t1)+gt(t3)) + t3*(LL)pow(10,gt(t1))+t1;
		LL p5 = t3*(LL)pow(10,gt(t2)+gt(t1)) + t1*(LL)pow(10,gt(t2))+t2;
		LL p6 = t3*(LL)pow(10,gt(t1)+gt(t2)) + t2*(LL)pow(10,gt(t1))+t1;
		printf("%lld\n",max(max(max(p1,p2),max(p3,p4)),max(p5,p6)));
	}

	return 0;
}

B
由贪心可知异或和为1的位肯定越高位越好,所以从高到低按位扫描,如果当前位为1,不作处理,否则算出将其变为1所需要的最小次数,然后将低位全部置为0。算出每一位的贡献排个序取前k小的,注意即使当前位某个数没被选上也要如此操作因为可能在后面的时候更优,即不只对前k个做上述操作。(也即,当某位确定为1时,所有数都需要该位变为1)

// by Balloons
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define mpr make_pair
#define debug() cerr<<"Madoka"<<endl
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f, maxn=2e5+5;

int n,m,k;
int a[maxn],b[maxn];
LL temp[maxn], lst[maxn];

signed main(){
	LL ans = 0;
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int d = 31;d>=0;d--){
		for(int i=1;i<=n;i++){
			temp[i] = lst[i];
			if((a[i] >> d) & 1);
			else temp[i] += (1ll<<(d)) - (a[i] % (1ll<<(d)));
		}
		sort(temp+1,temp+n+1);
		LL sum = 0;
		for(int i=1;i<=k;i++)sum += temp[i];
		if(sum <= m){
//			printf("?? %d\n",d);
//			for(int i=1;i<=n;i++)printf("%d ",temp[i]);puts("");
			ans |= (1ll<<d);
			for(int i=1;i<=n;i++){
				if((a[i] & (1ll<<d)) == 0){
					lst[i] += ((1ll<<d) - (a[i]%(1ll<<d)));
					a[i] = 0;
				}
			}
		}
	}
	printf("%lld\n",ans);

	return 0;
}

C
题意转化为求0 2n1的子集S个数,使得S没有一个子集T满足:T大小为偶数且异或和为0
考虑对一个大小为i的集合来说,有多少的数是加了之后不满足上述条件的?显然我们只需要考虑大小为奇数的子集,如果该子集的异或和为p,则p显然不能加入集合(注意这就是0 2n1这个条件的运用,p必定也是在该范围内的),现在我只需要统计异或和不同的大小为奇数的集合有多少即可
引理:对于某个集合M,对于其大小为奇数的子集合S  T如果ST不一样,则其异或和必不同
证明:考虑ST并集U,排除2次出现的元素之后大小必为偶数,也必为M的子集,若ST不一样且异或和相同则U大小为偶数且异或和为0,M不符合条件,矛盾
因此,异或和不同的大小为奇数的集合个数 = 大小为奇数的集合个数
C(i,1)+C(i,3)+...=2(|S|1)
考虑dp,设dp[i]表示大小为i的集合有多少符合条件的,答案即为dp[i]累加
dp[i]=dp[i1](2n2((i1)1))/i2(i2)即为大小为i1的集合中有多少大小为奇数的集合,除以i是因为有重复,dp[i1]中所有方案中的集合,设其中一个集合为S,则S中每一个元素当成"i",S中除了该元素外的集合并上i当成"S",又是一种转移,重复了i次
dp[0]=1,dp[1]=2n
显然只需要转移n次之后就都是0了

// by Balloons
#include <cstdio>
#include <set>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Madoka"<<endl
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f,mod=998244353;

int n;
int pw(int x,int y){
	if(!y)return 1;if(y==1)return x;
	int mid=pw(x,y>>1);
	if(y&1)return 1ll*mid*mid%mod*x%mod;
	return 1ll*mid*mid%mod;
}
int dp[200005];
int cnt,a[20005];
set<int>S;
void dfs(int l,int r){
	if(l == r+1){
		if((cnt&1)){
			int x = 0;
			for(int i=1;i<=cnt;i++)x ^= a[i];
			S.insert(x);
		}
		return ;
	}
	dfs(l+1,r);
	a[++ cnt]=l;
	dfs(l+1,r);
	-- cnt;
}
signed main(){
//	dfs(0,16);
//	printf("%d\n",S.size());	// N = 3, ans = 2^3; N = 4, ans = 2^4
//	return 0;
	scanf("%d",&n);
	dp[0] = 1;
	dp[1] = pw(2,n)%mod;
	LL ans = (dp[0]+dp[1])%mod;
	for(int i=2;i<=n+2;i++){
		dp[i] = 1ll*dp[i-1]*((pw(2,n) - pw(2,i-2)+mod)%mod)%mod*pw(i,mod-2)%mod;
		ans = (ans+dp[i])%mod;
	}
	printf("%d\n",ans);

	return 0;
}
posted @   SkyRainWind  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示