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" ;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端