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

 

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