自学内容网 自学内容网

Codeforces Round 959(Div. 1 + Div. 2)A~C

差点爆零了,最近div2打的越来越艰难了,好多不会累死,脑子完全不够用,上次div3刚上的绿就掉了

Codeforces Round 959(Div. 1 + Div. 2)

A. Diverse Game

链接:Problem - A - Codeforces

思路:

其实就是创建一个和之前不一样的矩阵就好了
解法一:我选择的方法是直接把第一行(或第一列)放在最后一行(或最后一列),其他都往前移就好了,顺序不变
解法二:就是在当前输入的数加一,如果这个数等于最大值就将其变为 1 1 1

代码:

解法一:

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 120;
int a[N][N];

void solve() {
  int n , m;
  cin >> n >> m;
  for(int i = 1 ; i <= n ; i++) {
    for(int j = 1 ; j <= m ; j++) {
      cin >> a[i][j];
    }
  }
  if(n == 1 && m == 1) {
    cout << -1 << endl;
    return;
  }
  if(n == 1) {
    cout << a[1][m] << " ";
    for(int i = 1 ; i < m ; i++) cout << a[1][i] << " ";
    cout << endl;
  } else if(m == 1) {
    cout << a[n][1] << endl;
    for(int i = 1 ; i < n ; i++) cout << a[i][1] << endl;
  } else {
    for(int i = 1 ; i <= m ; i++) cout << a[n][i] << " ";
    cout << endl;
    for(int i = 1 ; i < n ; i++) {
      for(int j = 1 ; j <= m ; j++) {
        cout << a[i][j] << " ";
      }
      cout << endl;
    }
  }
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  while(t--) solve();
  return 0;
}

解法二:

#include <bits/stdc++.h>
#define int long long
using namespace std;

void solve() {
  int n , m;
  cin >> n >> m;
  int N = n * m , x;
  for(int i = 1 ; i <= n ; i++) {
    for(int j = 1 ; j <= m ; j++) {
      cin >> x;
      if(N == 1) x = -1;
      else if(x == N) x = 1;
      else x++;
      cout << x << " ";
    }
    cout << endl;
  }
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  while(t--) solve();
  return 0;
}

B. Fun Game

链接:Problem - B - Codeforces

思路:

我们知道 1 1 1异或 0 或 1 0或1 01都会使其改变,而 0 0 0异或其他数都不会使其改变,所以我们要想改变当前这个数,那么这个数之前必须出现 1 1 1,或者他前面都是 0 0 0而他本身是 1 1 1,这样他自己异或他自己也会发生改变
1 1 1(位置都是从1开始):
s:010010
t:010000
要使 s [ 5 ] s[5] s[5]变化,那么就取 [ 1 , 2 ] [1,2] [1,2]这样 s [ 4 ] s[4] s[4]不变,而 s [ 5 ] s[5] s[5]发生变化
2 2 2
s:010010
t:000000
要使 s [ 2 ] s[2] s[2]变化,区间可以取 [ 1 , 2 ] [1,2] [1,2]这样 s [ 2 ] s[2] s[2]异或本身也会发生变化

综上所述:只要 s s s中的 1 1 1出现的比 t t t中的要早,那么就可以实现相互转换

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;

void solve() {
  int n;
  cin >> n;
  string s , t;
  cin >> s >> t;
  bool falg = true;
  for(int i = 0 ; i < n ; i++) {
    if(s[i] == '1') break;
    if(t[i] == '1') {
      falg = false;
      break;
    }
  }
  if(falg) cout << "YES" << endl;
  else cout << "NO" << endl;
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  while(t--) solve();
  return 0;
}

C. Hungry Games

链接:Problem - C - Codeforces

思路:

题意大概是给定一个数组,求这个数组中有多少个区间 [ l , r ] [l,r] [l,r]使得这个区间中所有的数相加不为零,当这个区间数超过 x x x之后,那么这一段为零,后面继续加的话,是从零开始加
例如:1、1、1、1 取 x = 2 x=2 x=2区间 [ 0 , 2 ] [0,2] [0,2]之和为 0 0 0是因为前三个数相加等于 3 3 3大于 2 2 2,所以要归零,而区间 [ 0 , 3 ] [0,3] [0,3]之和为 1 1 1,前面三个数归零了,加上第四个数,所以这个区间之和就是 1 1 1

我们可以逆着求,先求总共有 n ∗ ( n + 1 ) 2 \frac{n*(n + 1)}{2} 2n(n+1)种区间,再用总的数量减去区间和为零的区间,从后往前求即可。当然由于可以区间和为零时可以继续往后加,所以后面的会计算多次,所以最好是从后面开始算,然后累加

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;

void solve() {
  int n , x;
  cin >> n >> x;
  vector<int> a(n) , s(n + 1);//s为前缀和
  for(int i = 0 ; i < n ; i++) {
    cin >> a[i];
    s[i + 1] = s[i] + a[i];
  }
  int ans = n * (n + 1) / 2;//总共的区间数
  vector<int> dp(n + 1);//用来记录当前位置之后是否出现含有零的区间
  dp[n] = 1;
  for(int i = n  - 1 , j = n + 1 ; i >= 0 ; i--) {
    while(s[j - 1] - s[i] > x) j--;//当这个区间超过了x之后,j要往前移,使得这个区间之和的数始终小于等于x
    dp[i] = 1 + (j <= n ? dp[j] : 0);
    ans -= dp[i] - 1;
  }
  cout << ans << endl;
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  while(t--) solve();
  return 0;
}

原文地址:https://blog.csdn.net/ZYH_5201314/article/details/140575236

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!