Codeforces Round #648 (Div. 2)(A~E)

A. Matrix Game(思維)

分析

  • 題意
  1. 給我們一個 有0、1構成n * m的矩陣,現在有兩個人輪流進行操作,對於某次操作 當前玩家選擇任意一個表格,該表中元素爲0,且這個元素所在的行和列中的所有表格均沒有 出現元素1, 把這個表格中的0變成1,誰先無法 進行操作誰輸,問兩個玩家誰能贏(他們都已最優的狀態進行操作)
  • 思路
  1. 這一題看着像博弈題,但是卻不是,因爲當一個玩家在在進行選擇表格的時候,如果有多表格都可選擇的時候,其實這個時候無論他選擇 對那個表格進行操作,對下個玩家所造成的影響、對答案所造成的影響都是一樣的,舉個例子
1 0 0
0 0 0
1 0 0
  1. 在上面這個例子中,無論當前玩家選 對(2,2)或者(2,3)進行操作,所造成的影響都是一樣的,這個時候的不同選擇並無優劣之分,
  2. 因此產生的思路,就是 我們提前預處理 某行、某列 是否存在1,接着我們就 模擬填數的過程,看最後 總共進行了幾次操作

代碼

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

const int mxn = 2e2 + 10;

int mz[mxn][mxn];
int row[mxn];
int col[mxn];

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        memset(row, 0, sizeof(row));
        memset(col, 0, sizeof(col));
        int n, m;
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; i ++)        
            for(int j = 1; j <= m; j ++)
            {
                scanf("%d", &mz[i][j]);
                if(mz[i][j] == 1)
                    row[i] = 1, col[j] = 1;
            }

        int sum = 0;
        for(int i = 1; i <= n; i ++)
        {
            if(row[i] == 0)
            {
                for(int j = 1; j <= m; j ++)
                {
                    if(col[j] == 0)
                    {
                        sum ++;
                        row[i] = 1, col[j] = 1;
                        break;
                    }
                }
            }
        }

        if(sum % 2)
            printf("Ashish\n");
        else
            printf("Vivek\n");
    }

    return 0;
}

B. Trouble Sort(思維)

分析

  • 題意
  1. 給我們一個序列,這個序列中的元素值爲ai,類型爲bi = 0或1,如果在這個序列中 bi != bj ,我們可以交互兩個數的位置,問經過若干次這樣的操作之後,能否把這個序列變成 按ai值 非嚴格遞增?
  • 思路
  1. 先說結論:
    1. 如果這個序列中既存在bi=0,又存在bj = 1的兩種類型的數,就一定能夠 把序列變得非嚴格遞增,
    2. 如果僅存在類型爲1或0的數的話,這個時候我們直接判讀 這個序列是否爲 非嚴格遞增的,如果不是的話 輸出No
  2. 我們來舉個例子證明:結論1.
20 5 100 50
 0 1  1  1
  1. 在這個例子中,我們可以通過三次操作,把相同類型的兩個數字 進行位置交換,
    1.
    50 5 100 20
    
    50 5 20 100
    
    20 5 50 100
    
  2. 有了例子中的這種 交換方法,我們就可以通過 它 來變化出任意我們 需要的 序列排列(遞增、遞減等等)情況

代碼

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

const int mxn = 2e5 + 10;
int ar[mxn], br[mxn];

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int n;
        scanf("%d", &n);
        Pir fg(0,0);
        for(int i = 1; i <= n; i ++)
            scanf("%d", &ar[i]);
        bool zeng = 1;
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d", &br[i]);
            if(br[i] == 0)
                fg.fi = 1;
            else
                fg.se = 1;
            if(ar[i] - ar[i - 1] < 0)
                zeng = 0;
        }
        if(fg.fi && fg.se)
            printf("Yes\n");
        else if(zeng)
            printf("Yes\n");
        else
            printf("No\n");
    }


    return 0;
}


C. Rotation Matching

分析

  • 題意
  1. 給我們兩個數組a、b 他們的元素均在1~n之間,且每個元素僅出現一次,現在我們可以 向左向右滑動b(題目上是a數組)數組,任意k個位置,這樣操作之後b數組中的元素變爲:b[i] = b[(i + k)%n],問經過這樣的操作之後,a與b中對應元素相同的最大數是多少?
  • 思路
  1. 既然即可以 左右都可滑動,那麼我們只考慮向右滑動b數組元素 的這個操作就行了,
  2. 接着我們用桶排的方法統計出 b某個元素x,從它當前的位置i 滑動到a數組中對應的位置j需要的 需要向右滑動的距離k,這樣我們統計好b中所有元素有需要的相應的滑動距離之後,,
  3. 選出 桶中 值最大的那個 值就是我們的ans

代碼

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

const int mxn = 2e5 + 10;
int a[mxn], b[mxn];
int pa[mxn], pb[mxn];
int br[mxn];

int main()
{
    /* fre(); */
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)
        scanf("%d", &a[i]), pa[a[i]] = i;
    for(int j = 1; j <= n; j ++)
        scanf("%d", &b[j]), pb[b[j]] = j;
    
    for(int i = 1; i <= n; i ++)
    {
        br[(pa[i] - pb[i] + n) % n] ++;
    }
    int ans = 0;
    for(int i = 0; i < n; i ++)
    {
        ans = max(ans, br[i]);
    }
    printf("%d\n", ans);

    return 0;
}


D. Solve The Maze(bfs/dfs+貪心)

分析

  • 題意
  1. 給我們一個n*m的矩陣,矩陣中’.‘表示路,’#‘表示牆,‘G’、‘B’ 分別表示 好人 和壞人,現在 我們可在任意’.‘位置添加 牆’#’,問通過這個操作之後,我們能否令 好人 都能到達出口(n,m),而所有的壞人都不能到達出口
  • 思路
  1. 爲了不讓壞人到打出口,我們將 B 周圍的四個格子都設置爲 牆’#’,這樣的話能夠減少對路徑的佔用,是好人G有更大的可能到打出口,
  2. 這樣我們將所有的 B的周圍添加牆之後,我們桶(n,m) 跑一遍 dfs/bfs 去統計能夠遍歷到的人數設爲sum,我們可以預統計出 G的數量設爲cg,比較sum是否等於cg,如果等於的話說明所有的好人都可以到打出口,在所有的壞人都已經被牆圍着的情況下

代碼

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

const int mxn = 2e2 + 10;

char mz[mxn][mxn];
int mov[4][2] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
int sum = 0;
int n, m;
void dfs(int x, int y)
{
    for(int i = 0; i < 4; i ++)
    {
        int tx = x + mov[i][0];
        int ty = y + mov[i][1];
        if(tx < 1 || ty < 1 || tx > n || ty > m || mz[tx][ty] == '#') continue;
        if(mz[tx][ty] == 'G') sum ++;
        mz[tx][ty] = '#';
        dfs(tx, ty);
    }

}

bool judge(int x, int y)
{
    if(x >= 1 && y >= 1 && x <= n && y <= m && mz[x][y] == 'G')
        return true;
    return false;
}
void change(int x, int y)
{
    if(x >= 1 && y >= 1 && x <= n && y <= m && mz[x][y] != 'B')
        mz[x][y] = '#';
}

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        sum = 0;
        scanf("%d %d", &n, &m);
        int cg = 0;
        for(int i = 1; i <= n; i ++)
        {
            scanf("%s", mz[i] + 1);
            for(int j = 1; j <= m; j ++)
                if(mz[i][j] == 'G')
                    cg ++;
        }

        int fg = 1;
        for(int i = 1; i <= n; i ++)
        {
            for(int j = 1; j <= m; j ++)
                if(mz[i][j] == 'B' && judge(i, j + 1))
                {
                    fg = 0; break;
                }
                else if(mz[i][j] == 'B')
                {
                    change(i - 1, j);
                    change(i + 1, j);
                    change(i, j - 1);
                    change(i, j + 1);
                }
            if(! fg)
                break;
        }
        if(fg == 0)
        {
            printf("No\n");
            continue;
        }


        if(mz[n][m] == '#')
        {
            if(cg == 0)
                printf("Yes\n");
            else
                printf("No\n");
        }
        else
        {
            dfs(n, m);
            if(sum == cg)
                printf("Yes\n");
            else
                printf("No\n");
        }
    }


    return 0;
}


E. Maximum Subsequence Value(鴿巢原理??)

分析

  • 題意
  1. 給我們n個數我們可以從中選擇人k個數,要求這個k個數中在他們對應的二進制表示中的第i位,有不少於max(1, k-2)個數在他們的二進制位上是1,那麼這個第i位纔是有效的1(這有效的1的在十進制下所代表的答案才能對答案有貢獻),問這些總得貢獻的和 最大可以是多少?
  • 思路
  1. 先說結論:在n個數中,我們只需要選擇三個數(如果n<3的話就選擇n個數),就能得到我們符合題意的最大和了。
  2. 證明
    1. 我們假設 n > 3, 我們從n個數中選擇k(我們假設k≥3)個數,而在這個k個數中,至少有 k-2個數在二進制下第i位是1,是對答案有貢獻的(也就是說在最多有兩2個數在二進制下第i位爲0),
    2. 如果此時,我們在從 k中選擇3個數話,我們一定可確定至少有一個數在二進制下第i位位1,又因爲此時max(1, 3 - 2)= 1,只要求一個數有在二進制下第i位爲1,就可以對對答案產生貢獻,綜上3個數就可以到最大的答案了

代碼

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

const int mxn = 2e3 + 10;
ll ar[mxn];

int main()
{
    /* fre(); */
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)
        scanf("%lld", &ar[i]);
    ll ans = 0;
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            for(int k = 1; k <= n; k ++)
                ans = max(ans, ar[i] | ar[j] | ar[k]);
    printf("%lld", ans);

    return 0;
}

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