首页 > 其他分享 >ARC146 部分题解

ARC146 部分题解

时间:2022-09-03 17:25:06浏览次数:50  
标签:int 题解 异或 ARC146 集合 include 部分 dp define

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~2^n-1\)的子集\(S\)个数,使得\(S\)中没有一个子集\(T\)满足:\(T\)大小为偶数且异或和为0
考虑对一个大小为\(i\)的集合来说,有多少的数是加了之后不满足上述条件的?显然我们只需要考虑大小为奇数的子集,如果该子集的异或和为\(p\),则\(p\)显然不能加入集合(注意这就是\(0~2^n-1\)这个条件的运用,p必定也是在该范围内的),现在我只需要统计异或和不同的大小为奇数的集合有多少即可
引理:对于某个集合\(M\),对于其大小为奇数的子集合\(S\ \ T\)如果\(S\)和\(T\)不一样,则其异或和必不同
证明:考虑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[i-1] * (2^n - 2^{((i-1)-1)}) / i\),\(2^(i-2)\)即为大小为\(i-1\)的集合中有多少大小为奇数的集合,除以i是因为有重复,\(dp[i-1]\)中所有方案中的集合,设其中一个集合为\(S\),则S中每一个元素当成"i",S中除了该元素外的集合并上i当成"S",又是一种转移,重复了i次
\(dp[0]=1, dp[1]=2^n\)
显然只需要转移\(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;
}

标签:int,题解,异或,ARC146,集合,include,部分,dp,define
From: https://www.cnblogs.com/SkyRainWind/p/16653081.html

相关文章

  • P5914 [POI2004]MOS 题解
    题目传送门分析这是一道小学经典的数学题,对于这种求最短时间的题目,我们要认真考虑两组人员:首先,跑的快的人应当跑的最多,能者多劳。其次,跑的慢的人应当跑的最少,否则会拉......
  • CF1389B题解
    题目传送门题目分析首先,这道题比较的简单,是一道较为标准的dp,虽说有大佬说可以用贪心做,但本蒟蒻不会。首先,\(0\leqz\leq\min(5,k)\)所以我们可以开一个二维dp,......
  • 软件工程研究的最新进展第 1 部分
    软件工程研究的最新进展第1部分Photoby阿吉特梅斯特里on不飞溅1.基于神经进化的游戏测试和预言生成(arXiv)作者:帕特里克·费尔德迈尔,戈登弗雷泽抽象的......
  • Selenium 教程第 3 部分
    Selenium教程第3部分我真的很抱歉放弃这部续集。实际上,我在写这篇文章的时候就失去了动力,想着谁会去读它,甚至会喜欢它。但是看到您的一些支持者喜欢这个故事或添加到......
  • python | 算法大神左神(左程云)算法课程 二叉树部分【中】
    1.二叉树宽度......
  • 【题解】「COCI 2018.10」Teoretičar
    传送门题目大意有一个二分图,构造一种对边的染色方案,使得没有两个颜色相同的边共顶点。假设对于给定二分图的答案是\(C\),记\(X\)是大于等于\(C\)的最小的\(2\)的......
  • 「题解」Longge 的问题
    原题目链接:Link。虽然已经被A穿了但还是写一下。\[\sum_{i=1}^n\gcd(i,n)=\sum_{d\vertn}\sum_{i=1}^n[\gcd(i,n)=d]\]这一步显然,因为\(\forall\gc......
  • P2858 [USACO06FEB]Treats for the Cows G/S 题解
    [USACO06FEB]TreatsfortheCowsG/S[USACO06FEB]TreatsfortheCowsG/S题目描述FJhaspurchasedN(1<=N<=2000)yummytreatsforthecowswhogetmoneyfo......
  • 大部分的中国人
    拖着疲惫不堪的身体回到租房,妻子低声数落着柴米油盐贵,不知何时能剩下钱买房,顽皮的孩子看着电视剧,被你责备撵去写功课,年迈的父母体力不及当年,在乡下守着二亩地望子成龙,可你......
  • P1005 [NOIP2007 提高组] 矩阵取数游戏 题解
    luogu原题传送门[NOIP2007提高组]矩阵取数游戏题目描述帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的\(n\timesm\)的矩阵,矩阵中的每个元素\(a_{i,j}\)均为非......