Codeforces Round #764

Codeforces Round #764 (Div. 3)

A. Plus One on the Subset

1)题目大意:

给一个序列,每次可以选几个数加一。问最少做几次操作可以使得整个序列数值相等。

2)思路:

答案就是最大值最小值之差、

3)代码
//略

B. Make AP

1)题目大意:

给三个正整数abc,问是否可能存在一个正整数m,使得(a,b,c)或(a * m,b,c)或(a,b * m,c)或(a,b,c * m)成为等差数列。

2)思路:

ab之间,bc之间,ac之间分别有三个d。根据d算出等差数列的第三个数,若该数字非负且可以被对应位置的数整除就出YES

当然ac之间的公差d不能是奇数,(可以是负数,但是负数取模就可能有问题)

3)代码:
string solve(){

	cin >> a >> b >> c ;
	
	ll d = b - a ;
	
	if(b + d > 0 && (b + d) % c == 0) return "YES\n" ;
	
	d = c - b ;
	
	if(b - d > 0 && (b - d) % a == 0) return "YES\n" ;
	
	if(abs(c - a) % 2 == 1) return "NO\n" ;//负数判断奇偶
	
	d = (c - a) / 2 ; 
	
	if(a + d > 0 && (a + d) % b == 0) return "YES\n" ;
	return "NO\n" ; 
	
}
5)大佬的代码:

笨蛋才像我这样写公差啊,大佬都是用a+c = 2*b的。雀食蟀啊!

string solve(){

	cin >> a >> b >> c ;
	
	if((2 * b - c) % a == 0 && (2 * b - c) > 0) return "YES" ;
	if((2 * b - a) % c == 0 && (2 * b - a) > 0) return "YES" ;
	if((a + c) % 2 == 0 && ((a + c >> 1) % b == 0) && ((a + c >> 1) > 0)) return "YES" ;
	return "NO" ;
	
}

C. Division by Two and Permutation

1)题目大意:

给一串数字,可以对任意一个数字整除2若干次,问有没有可能可以构造出n的排列。

2)思路:

n是50,那就n^2直接做。从n枚举到1,一个数一个数去找,复杂度大致是n2logn。

3)代码:
void solve(){
	bool b[100] = {} ;
	cin >> n ;
	get1(a , n) ;
	m = n ;
	for(int i = n ; i >= 1 ; i -- ){
		bool f = 0 ;
		for(int j = 1 ; j <= n ; j ++ ){
			if(b[j]) continue ;
			if(a[j] == i){
				f = 1 ; b[j] = 1 ;
			}
			while(a[j] >= i && !f){
				a[j] /= 2 ;
				if(a[j] == i){
					f = 1 ; break ;
				}
			}
			if(f){
				b[j] = 1 ;break ;
			}
			
		}
		if(!f){
			cout << "NO\n" ; return ;
		}
	}
	cout << "YES\n" ;
}

D. Palindromes Coloring

1)题目大意:

给一个长度为n的字符串s,给颜色种类k。不是每个字符都要涂色,但是每种颜色都必须涂色。把涂同一种颜色的字母拿出来可以构造出k个字符串,这k个字符串中字符可以随意交换顺序。问构造出k个回文串的最小长度的最大值是多少。

2)思路:

这一场止步于此啊,这题卡了两个小时...

我当时的想法是做一个优先队列,然后尽量把所有的k条串都往平均值长度靠拢。但是这样确实不ok。赛后看到了两种解法:直接算和二分答案。

法一:直接算

先算出最多有多少个字符对,即有多少对一样的字符。字符对是可以随意放到k个串中的。再就是找有多少个奇数。先把字符对平均分给k个串得到基准长度。再看能不能在k个偶数回文串里插入一个字符。若剩余的字符对里的字符数量加上奇数的数量大于k,则可以把最小值增加1 。(aaaaaa <= b)

void solve(){
	ll abt[30] = {} ;
	cin >> n >> k >> s ;
	for(char c : s)abt[c - 'a'] ++ ;
	
	ll numPair = 0 , numOdd = 0 ;//对数和奇数数量
	
	for(int i = 0 ; i < 30 ; i ++ ){
		numPair += abt[i] / 2 ;
		numOdd += abt[i] % 2 ? 1 : 0 ;
	}
	
	ll ans = numPair / k * 2 ;
	if(numPair % k * 2 + numOdd >= k)ans ++ ;
	cout << ans << "\n" ;
	
}

法二:二分答案

要找最小值的最大值,那么第一反应是二分。

枚举答案,即枚举k条串里的最短长度,算出k条的字符x对数量和总字符对数量numPair比较。少了就向上二分。

要注意的是二分初始条件,以后做题需要做好上下限,即初始lr 的值。

ll numPair ;
bool ck(ll x){
	return x / 2 * k <= numPair ;
}

void solve2(){
	numPair = 0 ;
	for(int i = 0 ; i < 30 ; i ++ ) abt[i] = 0 ;
	
	cin >> n >> k >> s ;
	for(char c : s)abt[c - 'a'] ++ ;
	
	for(int i = 0 ; i < 30 ; i ++ )numPair += abt[i] / 2 ;
	
	ll l = 0 , r = n / k ;
	
	while(l < r){
		ll mid = l + r + 1 >> 1 ;
		//cout << mid << " " << ck(mid) << "\n" ;
		if(ck(mid)) l = mid ;
		else r = mid - 1 ;
	}
	cout << l << "\n" ;

}

G. MinOr Tree

1)题解传送门:

G. MinOr Tree - tyrii

posted @   tyrii  阅读(113)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示