A:https://codeforces.com/contest/1151/problem/A
题意:给你字符串,对于字符串中的每一个字符,你都可以进行n次前进(如:A->B)或者后退(如B->A),其中A后退即为Z,Z前进即为A。要在字符串中得到一个子串"ATCG",整个字符串最多要前进或者后退多少次。
思路:由于字符串长度最大50,而子串长度固定为4,所以可以直接在字符串中进行朴素匹配。
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s, 0, sizeof(s))
const int inf = 0x3f3f3f3f;
#define LOCAL
int n;
string s;
int main()
{
#ifdef LOCAL
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
cin >> n >> s;
int ans = 0x3f3f3f3f;
for(int i = 0; i < n-3; ++i){
int cnt = 0;
cnt += min(abs(s[i]-'A'), 26+min(s[i], 'A')-max(s[i], 'A'));
cnt += min(abs(s[i+1]-'C'), 26+min(s[i+1], 'C')-max(s[i+1], 'C'));
cnt += min(abs(s[i+2]-'T'), 26+min(s[i+2], 'T')-max(s[i+2], 'T'));
cnt += min(abs(s[i+3]-'G'), 26+min(s[i+3], 'G')-max(s[i+3], 'G'));
ans = min(ans, cnt);
}
cout << ans << endl;
return 0;
}
B:https://codeforces.com/contest/1151/problem/B
题意:给你一个二维数组(n*m),从每一行中选出一个数,问是否存在一种选择方案,使得选出的这n个数的异或和大于0。若不存在这种方案,输出"NIE"; 存在的话,输出“TAK”,并接着输出选择方案:即每一行中被选出的数字所在行的下标。
思路:对于每一行,都选择第一个数字,求一下异或和,如果大于0了,那么这种方案即可行,那么直接输出n个1即可。如果其异或和为0,那么只要遍历每一行,如果存在某一行,存在一个数和该行的第一个数(即之前的方案中所选择的数)不一样,那么在之前的方案中用这个数替代第一个数即可。
总结:这里用异或的一个很重要的性质:对于两个整数,如果它们的异或和为0,当且仅当这两个数相等。
对这个性质拓展一下,可以发现,如果n个数的异或和为0,那么可以取出这n个数中的任意一个数,假设这个数位9,那么剩下的(n-1)数的异或和也一定和这个数相等,即为9。
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s, 0, sizeof(s))
const int inf = 0x3f3f3f3f;
#define LOCAL
#define N 600
int n, m;
int arr[N][N];
int main()
{
#ifdef LOCAL
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
cin >> n >> m;
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j)
cin >> arr[i][j];
}
int cnt = 0;
for(int i = 0; i < n; ++i)
cnt ^= arr[i][0];
if(cnt > 0){
cout << "TAK" << endl;
for(int i = 0; i < n-1; ++i)
cout << 1 << ' ';
cout << 1 << endl;
return 0;
}else{
std::vector<int> v;
int flag = 0;
for(int i = 0; i < n; ++i){
if(flag){
v.push_back(1);
continue;
}
int j;
for(j = 1; j < m; ++j){
if(arr[i][j] != arr[i][0]){
v.push_back(j+1);
flag = 1;
break;
}
}
if(j == m){
v.push_back(1);
}
}
if(flag){
cout << "TAK" << endl;
for(int i = 0; i < n-1; ++i)
cout << v[i] << ' ';
cout << v[n-1] << endl;
}else{
cout << "NIE" << endl;
}
}
return 0;
}
D:https://codeforces.com/contest/1151/problem/D
题意:有n个学生,对于每个学生,有两个值:a和b。该位置对应一个值:T=ai⋅(j−1)+bi⋅(n−j)。其中j为学生所在的位置序号,你可以对学生进行任意排序,要求所有的T之和最小。求这个最小的T值。
思路:对ai⋅(j−1)+bi⋅(n−j)进行化简可以得到: j*(ai-bi)+(n*bi-ai), 由于是求所有T之和,所以(n*bi-ai)之和是一个常量,所以只要考虑前面那项:j*(ai-bi)。很容易发现,对于每一个学生,如果其(ai-bi)越小,越应该排在后面,所以只要对这n个学生按照(a-b)进行降序排序即可。
注意:此题会爆int,改用long long即可。
误区:这道题我一直陷入这个表达式的逻辑意义:(j-1)为与左端的距离,(n-j)为与右端的距离,所以一直在想对于每一个学生,用什么量衡量他是适合左端,还是右端。。。。。结果不断换这个衡量量 。。却连样例也没过。。
总结:遇到表示式,试试化简!化简!化简!
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s, 0, sizeof(s))
const ll inf = 0x3f3f3f3f;
#define LOCAL
#define N 100000+50
struct node{
ll a, b;
};
ll n;
node arr[N];
bool cmp(node x, node y){
return (x.a-x.b) > (y.a-y.b);
}
int main()
{
#ifdef LOCAL
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
cin >> n;
for(ll i = 0; i < n; ++i){
cin >> arr[i].a >> arr[i].b;
}
sort(arr, arr+n, cmp);
ll cnt = 0;
for(ll i = 0; i < n; ++i){
//printf("a:%d b:%d\n", arr[i].a, arr[i].b);
cnt += arr[i].a*(i-0)+arr[i].b*(n-1-i);
}
cout << cnt << endl;
return 0;
}