Codeforces Round #553 (Div. 2)

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章