Codeforces Round #750 (Div. 2)
总的来说挺失败的,签到题卡的比后面的题还要久,雀氏菜
A. Luntik and Concerts
传送门
A最简单但卡的最久,果然是思维题硬伤,写了一大堆还抵不过栋哥哥三四行代码,多吃点核桃补补呜呜呜
题意:给你三首分别为一分钟,两分钟,三分钟的歌,歌曲数量为a,b,c,把所有的歌安排到两场比赛中,使得两场比赛各自的总时间差值最小
题解:我们简单模拟可以知道插值要么是0,要么是1,我们可以把三首歌各自的数量q取余2,结果就是(a+2b+3c)%2,原因是,若1分钟和2分钟取余后剩1(2分钟和3分钟剩1同理),当三分钟取余后是0,那么就让1分钟和2分钟的歌分到两场比赛,差值就是1;若1分钟和3分钟剩1,当2分钟取余后为0,那么说明2分钟的歌至少有2个,我们让1分钟和3分钟在一场比赛,跟两个2分钟抵消就可;当a,b,c都剩余1,那么就让1分钟和2分钟凑一起,抵消3分钟
code:
# include <iostream>
# include <algorithm>
# include <string.h>
# include <cstring>
using namespace std;
int main(){
int n;
cin >> n;
while (n --){
int a, b, c;
cin >> a >> b >> c;
a%=2,b%=2,c%=2;
b*=2,c*=3;
cout << (a+b+c)%2 << endl;
}
return 0;
}
B. Luntik and Subsequences
传送门
题意:求有多少种子序列,可以通过删除序列某些数(或不删除),使得子序列的和等于这个序列总和sum 减去一
题解:我们统计序列1的个数num1,这样可以删除num1次,在统计0的个数num0,0可以删除:由(0)变成(),因此答案就是num1*pow(2,num0)
code:
#include <iostream>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int ans[2010];
int st[2021];
int a[100];
ll fast (ll b){
ll ans = 1;
ll a = 2, p = 1e9 + 10;
while (b){
if (b % 2) ans *= a ;
b /= 2;
a = a * a ;
}
return ans;
}
int main(){
int t;
cin >> t;
while (t --){
ll n,k;
ll num1 = 0, num0 = 0;
cin >> n;
for (ll i = 1; i <= n; i ++){
cin >> k;
if (k == 1)
num1 ++;
else if (k == 0)
num0 ++;
}
cout << num1 * fast(num0) << endl;
}
return 0;
}
C. Grandma Capa Knits a Scarf
传送门
题意:让你删除某一个字符,可重复删除,但不能删除别的字符,(或者不删除),使得它是回文字符,求解删除字符个数最少的情况是几个
题解:由于字符实在a~z之间,我们直接枚举就好了,从a开始枚举,运用双指针,指向最左和最右两点,如果这两点数值相同,就继续向中间遍历,如果左边或者右边的字符等于外层遍历的字符,说明可以删除它,ans++,再继续移动指针,如果左右两边不相等且不等于外层遍历的字符,直接跳出就可,不存在回文字符
#include <iostream>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
char a[N];
ll fast (ll b){
ll ans = 1;
ll a = 2, p = 1e9 + 10;
while (b){
if (b % 2) ans *= a ;
b /= 2;
a = a * a ;
}
return ans;
}
int main(){
int t;
cin >> t;
while (t --){
int n;
cin >> n;
string s;
cin >> s;
int res = N;
for (char ch = 'a'; ch <= 'z'; ch ++){
int l = 0, r = n - 1;
int ans = 0;
while (l < r){
if (s[l] == s[r]) l ++, r --;
else if (s[l] == ch) l ++, ans ++;
else if (s[r] == ch) r --, ans ++;
else{
ans = n + 100;
break;
}
}
res = min (res , ans);
}
if (res == n + 100) res = -1;
cout << res << endl;
}
return 0;
}
D. Vupsen, Pupsen and 0
传送门
这题张师姐巴拉巴拉讲一堆也没听懂,自己看了看,就是个简单的奇偶性问题,不过坑还是很多的
题意:给你一个不含有0的数组a[i],让你写出另一个等长的不含有0的数组b[i],使得这两个数组乘积和a[1]*b[1] + ... 等于 0
题解:数组个数是偶数,数组b就让它跟a数组两两抵消,如{a,b}和{-b,a},数组个数为奇数,前n-3项按照偶数处理,剩下三个,也可以推测抵消方式(我觉得这是这题最恶心的地方),而且要注意不能为0
code:
#include <iostream>
#include <cstring>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <math.h>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int main(){
int t;
cin >> t;
while (t --){
int n;
cin >> n;
for (int i = 1; i <= n; i ++)
cin >> a[i];
if(!(n & 1)){
for (int i = 1; i <= n; i += 2)
cout << -1 * a[i + 1] << ' ' << a[i] << ' ';
cout << endl;
}
else{
for (int i = 1; i <= n - 3; i += 2)
cout << -1 * a[i + 1] << ' ' << a[i] << ' ';
int x = a[n - 2];
int y = a[n - 1];
int z = a[n];
if(x + z != 0)
printf("%d %d %d\n", y, -(x + z), y);
else if(x + y != 0)
printf("%d %d %d\n", z, z, -(x + y));
else
printf("%d %d %d\n", -(z + y), x, x);
}
}
return 0;
// 2 1 1 -> 1 1 -3
// 1 -1 2 -> -1 -3 -1
}

浙公网安备 33010602011771号