Codeforces Round #420 (Div. 2)

A Okabe and Future Gadget Laboratory

Okabe needs to renovate the Future Gadget Laboratory after he tried doing some crazy experiments! The lab is represented as an n by n square grid of integers. A good lab is defined as a lab in which every number not equal to 1 can be expressed as the sum of a number in the same row and a number in the same column. In other words, for every x, y such that 1 ≤ x, y ≤ n and ax, y ≠ 1, there should exist two indices s and t so that ax, y = ax, s + at, y, where ai, j denotes the integer in i-th row and j-th column.
Help Okabe determine whether a given lab is good!

n * n的网格里(n <= 50),考虑每个不等于1的位置,在该行与该列上是否分别存在一个数,使得它们的和等于该位置的值,如果都存在输出“Yes”, 否则输出“No”。暴力枚举即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
int g[100][100];
int main(){
  cin >> n;
  for(int i = 1; i <= n; i++)
    for(int j = 1;j <= n; j++)
      cin >> g[i][j];
    bool fg = false;
  for(int i = 1; i <= n; i++)
    for(int j = 1; j <= n; j++){
      fg = false;
      if(g[i][j] == 1) continue;
      else{
        for(int p = 1; p <= n; p++){
          for(int q = 1; q <= n; q++){
            if(!(p == j && q == i)){
              if(g[i][p]+g[q][j] == g[i][j]){
                fg = true;break;
              }
            }
          }
          if(fg) break;
        }
        if(fg == false) {cout << "No"; return 0;}
      }
    }
    cout << "Yes" << endl;
  return 0;
}

B Okabe and Banana Trees
Okabe needs bananas for one of his experiments for some strange reason. So he decides to go to the forest and cut banana trees.

Consider the point (x, y) in the 2D plane such that x and y are integers and 0 ≤ x, y. There is a tree in such a point, and it has x + y bananas. There are no trees nor bananas in other points. Now, Okabe draws a line with equation y=−x/m+b. Okabe can select a single rectangle with axis aligned sides with all points on or under the line and cut all the trees in all points that are inside or on the border of this rectangle and take their bananas. Okabe’s rectangle can be degenerate; that is, it can be a line segment or even a point.

Help Okabe and find the maximum number of bananas he can get if he chooses the rectangle wisely.

Okabe is sure that the answer does not exceed 1018. You can trust him.

link

直接看样例1的图,m和b带入公式得到这样一条直线,图上每一个整点的值等于横纵坐标之和,在直线下方与坐标轴正半轴构成一个矩形,问这个矩形包含的值最大等于多少(只考虑整点,包含边界)。
直线与坐标轴交于(bm,0),(0,b)两点,确定右上角的点的位置就确定了整个矩形,然后等差数列求和,就得到了矩形的值,三分或者直接暴力可以得到最大值。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int b,m;
ll f(ll x){
  return floor(double(b) - double(x*1.0/m));
}
ll cal(ll x, ll y){
  ll t = y * (y+1)/2;
  return (t+t+x*(y+1)) * (x+1)/2;
}
int main(){
  cin >> m >> b;
  ll ans = 0;
  for(ll i = 0; i <= b*m; i++){
    ans = max(cal(i,f(i)), ans);
  }
  cout << ans << endl;
  return 0;
}

C Okabe and Boxes

Okabe and Super Hacker Daru are stacking and removing boxes. There are n boxes numbered from 1 to n. Initially there are no boxes on the stack.

Okabe, being a control freak, gives Daru 2n commands: n of which are to add a box to the top of the stack, and n of which are to remove a box from the top of the stack and throw it in the trash. Okabe wants Daru to throw away the boxes in the order from 1 to n. Of course, this means that it might be impossible for Daru to perform some of Okabe’s remove commands, because the required box is not on the top of the stack.

That’s why Daru can decide to wait until Okabe looks away and then reorder the boxes in the stack in any way he wants. He can do it at any point of time between Okabe’s commands, but he can’t add or remove boxes while he does it.

Tell Daru the minimum number of times he needs to reorder the boxes so that he can successfully complete all of Okabe’s commands. It is guaranteed that every box is added before it is required to be removed.

模拟进栈出栈,出栈顺序必须递增。

#include <bits/stdc++.h>
using namespace std;
int n;
int main()
{
  stack<int> s;
  cin >> n;
  int cur = 1,ans = 0;
  char str[100];
  for(int i = 1; i <= 2 *n; i++){
    cin >> str;
    if(str[0] == 'a'){
      int t;
      cin >> t;
      s.push(t);
    }
    else{
      if(!s.empty()){
        if(s.top() == cur) s.pop();
        else{
          ans++;
          while(!s.empty()) s.pop();
        }
      }
    cur++;
    }
  }
  cout << ans << endl;
  return 0;
}

D Okabe and City

Okabe likes to be able to walk through his city on a path lit by street lamps. That way, he doesn’t get beaten up by schoolchildren.

Okabe’s city is represented by a 2D grid of cells. Rows are numbered from 1 to n from top to bottom, and columns are numbered 1 to m from left to right. Exactly k cells in the city are lit by a street lamp. It’s guaranteed that the top-left cell is lit.

Okabe starts his walk from the top-left cell, and wants to reach the bottom-right cell. Of course, Okabe will only walk on lit cells, and he can only move to adjacent cells in the up, down, left, and right directions. However, Okabe can also temporarily light all the cells in any single row or column at a time if he pays 1 coin, allowing him to walk through some cells not lit initially.

Note that Okabe can only light a single row or column at a time, and has to pay a coin every time he lights a new row or column. To change the row or column that is temporarily lit, he must stand at a cell that is lit initially. Also, once he removes his temporary light from a row or column, all cells in that row/column not initially lit are now not lit.

Help Okabe find the minimum number of coins he needs to pay to complete his walk!

bfs搜索题,从左上角到右下角,必须走在有灯的格子里,如果要去的格子没有灯,可以暂时照亮任意一行或者一列,但必须之前站在原来就是有灯的格子里,同时花费为1,问是否能到达目的地,如果能输出最小花费,否则输出-1。
分析下来有以下几点:

    每次bfs都是在原始就是有灯的点之间移动(除了终点)
    一行或者一列最多被照亮一次
    当前点,与下一次可以到达的点的横坐标或纵坐标距离小于等于2
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a));
#define pb push_back
using namespace std;
const int maxn = 10000 + 50;
const int MAXN = (1<<30);
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
priority_queue<pii, vector<pii>, greater<pii> > pq;
map<pii, int> label;
vi r[maxn], c[maxn];
vector<pii> lights;
bool dr[maxn], dc[maxn];
int dirx[4] = {0,-1,0,1};
int diry[4] = {-1,0,1,0};
int dist[maxn];
int n, m, k;
void Init(){
  while(!pq.empty()) pq.pop();
  label.clear();
  for(int i = 0; i < maxn; i++){
    r[i].clear();
    c[i].clear();
    dist[i] = MAXN;
    dr[i] = dc[i] = false;
  }
    lights.clear();
}
void filrow(int row, int val){
  if(row >= 1 && row <= n && !dr[row]){
    dr[row] = true;
    for(auto x : r[row]) if(dist[x] > val){
      dist[x] = val;
      pq.push({dist[x], x});
    }
  }
}
void filcol(int col, int val){
  if(col >= 1 && col <= m && !dc[col]){
    dc[col] = true;
    for(auto y : c[col]) if(dist[y] > val){
      dist[y] = val;
      pq.push({dist[y], y});
    }
  }
}
void ad(int x, int y, int val){
  if(label.find({x, y}) != label.end()){
    if(dist[label[{x, y}]] > val) {
      dist[label[{x, y}]] = val;
      pq.push({val, label[{x, y}]});
    }
  }
}
int main(){

  ios::sync_with_stdio(false);
  cin.tie(0);cout.tie(0);
  while(cin >> n >> m >> k){
    Init();
    for(int i = 0; i < k; i++){
      int x, y;
      cin >> x >> y;
      r[x].pb(i);
      c[y].pb(i);
      lights.pb({x, y});
      label[{x, y}] = i;
    }
    if(label.find({n, m}) == label.end()){
      filrow(n, 1);
      filrow(n-1, 1);
      filcol(m, 1);
      filcol(m-1, 1);
    }else pq.push({0, label[{n, m}]});

    while(!pq.empty()){
      auto a = pq.top();pq.pop();
      int d = a.first;
      int p = a.second;
      if(d > dist[p]) continue;
      for(int i = 0; i < 4; i++) 
        ad(lights[p].first + dirx[i], lights[p].second + diry[i], d);
      for(int i = lights[p].first - 2; i <= lights[p].first + 2; i++)
        filrow(i, d+1);
      for(int i = lights[p].second - 2; i <= lights[p].second + 2; i++)
        filcol(i, d+1);
    }
    if(dist[0] == MAXN) cout << "-1" << endl;
    else cout << dist[0] << endl;
  }
  return 0;
}

E Okabe and El Psy Kongroo

Okabe likes to take walks but knows that spies from the Organization could be anywhere; that’s why he wants to know how many different walks he can take in his city safely. Okabe’s city can be represented as all points (x, y) such that x and y are non-negative. Okabe starts at the origin (point (0, 0)), and needs to reach the point (k, 0). If Okabe is currently at the point (x, y), in one step he can go to (x + 1, y + 1), (x + 1, y), or (x + 1, y - 1).

Additionally, there are n horizontal line segments, the i-th of which goes from x = ai to x = bi inclusive, and is at y = ci. It is guaranteed that a1 = 0, an ≤ k ≤ bn, and ai = bi - 1 for 2 ≤ i ≤ n. The i-th line segment forces Okabe to walk with y-value in the range 0 ≤ y ≤ ci when his x value satisfies ai ≤ x ≤ bi, or else he might be spied on. This also means he is required to be under two line segments when one segment ends and another begins.

Okabe now wants to know how many walks there are from the origin to the point (k, 0) satisfying these conditions, modulo 10^9 + 7.
从(0,0) 到(k,0),每个点可以到达右上,右,右下这三个点,但必须在c下方,0上方(包括0边界),问最终到达(k,0)有多少种方案。

dp,因为ci是一条与x轴平行的线段,所以从ai到ai+1的每一次的贡献都是一样的,可以用矩阵加速,c最多为15,所以不会超时

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
struct matrix{
  ll val[16][16];
  matrix(){memset(val,0,sizeof(val));}
  matrix operator*(const matrix & rhs)const{
    matrix ret;
    for(int i = 0; i < 16; i++)
      for(int j = 0; j < 16; j++)
        for(int k = 0; k < 16; k++)
          ret.val[i][j] += val[i][k] * rhs.val[k][j]%mod,
          ret.val[i][j] %= mod;
    return ret;
  }
};
matrix pow_mod(const matrix& b, ll p){
  matrix ret, cur = b;
  for(int i = 0; i < 16; i++)
    ret.val[i][i] = 1;
  while(p){
    if(p & 1)
      ret = ret * cur;
    cur = cur * cur;
    p>>=1;
  }
  return ret;
}
int n;
ll k;
int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);cout.tie(0);
  cin >> n >> k;
  matrix ans;
  ans.val[0][0] = 1;
  for(int i = 1; i <= n; i++){
    ll a, b;
    int c;
    cin >> a >> b >> c;
    matrix mul;
    for(int j = 0; j <= c; j++)
      for(int l = j-1; l <= j+1; l++)
        if(l >= 0 && l <= c)
          mul.val[j][l] = 1;
    ans = pow_mod(mul, min(b,k) - a) * ans;
  }
  cout << ans.val[0][0] << endl;
  return 0;
}
posted @ 2018-03-16 08:59  foreignbill  阅读(201)  评论(0)    收藏  举报