「題解」The 19th Zhejiang Provincial Collegiate Programming Contest

Before

比賽

清明和一個隊友 vp 的,完全的跟榜做題,感覺發揮的還行。

B - JB Loves Comma

簽到

#include <bits/stdc++.h>

std::string s;

int main() {
  std::cin >> s;
  int n = s.length();
  for (int i = 0; i < n; ++i) {
    putchar(s[i]);
    if (i >= 2 && s[i] == 'b' && s[i - 1] == 'j' && s[i - 2] == 'c') putchar(',');
  }
  return 0;
}

C - JB Wants to Earn Big Money

簽到

#include <bits/stdc++.h>

int n, m, x;

int main() {
  scanf("%d %d %d", &n, &m, &x);
  int ans = 0;
  for (int i = 1, a; i <= n; ++i) {
    scanf("%d", &a);
    if (a >= x) ++ans;
  }
  for (int i = 1, a; i <= m; ++i) {
    scanf("%d", &a);
    if (a <= x) ++ans;
  }
  printf("%d\n", ans);
  return 0;
}

A - JB Loves Math

分類討論

  • \(a = b\),答案爲 \(0\)
  • \(a < b\)
    • \(b - a\) 爲奇數,答案爲 \(1\)
    • \(b - a\) 爲偶數,加兩次奇數減一次偶數可以完成,還要考慮加偶數次奇數的情況,兩者取最小值
  • \(a > b\)
    • \(a - b\) 爲奇數,答案爲 \(2\)
    • \(a - b\) 爲偶數,答案爲 \(1\)
#include <bits/stdc++.h>

int T;

int min(int x, int y) { return x < y ? x : y; }

int main() {
  scanf("%d", &T);
  while (T--) {
    int a, b;
    scanf("%d %d", &a, &b);
    if (a == b) puts("0");
    else if (a < b) {
      if ((b - a) & 1) puts("1");
      else {
        int cnt = 1, x = (b - a);
        while (!(x & 1)) cnt *= 2, x >>= 1;
        printf("%d\n", min(cnt, 3));
      }
    } else {
      if ((a - b) & 1) puts("2");
      else puts("1");
    }
  }
  return 0;
}

賽時想當然了,罰時了兩發。

L - Candy Machine

將糖果按甜度由小到大排序,選擇的子集一定是從第一個糖果到某個糖果(爲了使平均值儘量小)。

用雙指針方法維護有多少糖果甜度大於平均值。

#include <bits/stdc++.h>
#define N 1000001

typedef long long ll;

int n, ans, a[N];

int max(int x, int y) { return x > y ? x : y; }

int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
  std::sort(a + 1, a + n + 1);
  int l = 1, r = 0;
  ll sum = 0;
  while (r < n) {
    ++r;
    sum += a[r];
    double avg = 1.0 * sum / r;
    while (l <= r && a[l] - avg <= 0) ++l;
    ans = max(ans, r - l + 1);
  }
  printf("%d\n", ans);
  return 0;
}

G - Easy Glide

可以發現有用的點只有幾個滑翔點和起點終點,幾個點之間互相建邊,邊長爲所需時間(可以通過簡單數學計算的出)。然後跑最短路。

#include <bits/stdc++.h>
#define N 1518
#define inf 2147483647
#define fir first
#define sec second

typedef std::pair<double, int> pdi;

bool vis[N];
double dis[N];
int ecnt, head[N];
int n, v1, v2, x[N], y[N];
struct Edge {
  double w;
  int nxt, v;
}e[N * N];

void add(int u, int v, double w) {
  e[++ecnt].v = v, e[ecnt].w = w;
  e[ecnt].nxt = head[u], head[u] = ecnt;
}

double getd(int x_, int y_ ) {
  // return abs(x[x_] - x[y_]) + abs(y[x_] - y[y_]);
  return (double)sqrt(1ll * (x[x_] - x[y_]) * (x[x_] - x[y_]) + 1ll * (y[x_] - y[y_]) * (y[x_] - y[y_]));
}

void Dij() {
  for (int i = 1; i <= n + 2; ++i) dis[i] = inf;
  dis[n + 1] = 0;
  std::priority_queue<pdi, std::vector<pdi>, std::greater<> > q;
  q.push({dis[n + 1], n + 1});
  while (!q.empty()) {
    pdi u = q.top();
    q.pop();
    if (vis[u.sec]) continue;
    vis[u.sec] = true;
    for (int i = head[u.sec]; i; i = e[i].nxt) {
      int v = e[i].v;
      if (!vis[v] && dis[v] > dis[u.sec] + e[i].w) {
        dis[v] = dis[u.sec] + e[i].w;
        q.push({dis[v], v});
      }
    }
  }
}

int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; ++i) {
    scanf("%d %d", &x[i], &y[i]);
  }
  scanf("%d %d %d %d", &x[n + 1], &y[n + 1], &x[n + 2], &y[n + 2]);
  scanf("%d %d", &v1, &v2);
  add(n + 1, n + 2, 1.0 * getd(n + 1, n + 2) / v1);
  for (int i = 1; i <= n; ++i) {
    add(n + 1, i, 1.0 * getd(i, n + 1) / v1);
    double d = getd(i, n + 2);
    add(i, n + 2, (d <= v2 * 3) ? (1.0 * d / v2) : (3.0 + 1.0 * (d - v2 * 3.0) / v1));
    for (int j = 1; j <= n; ++j) {
      if (i == j) continue;
      else {
        d = getd(i, j);
        add(i, j, (d <= v2 * 3) ? (1.0 * d / v2) : (3.0 + 1.0 * (d - v2 * 3.0) / v1));
      }
    }
  }
  Dij();
  printf("%.12lf", dis[n + 2]);
  return 0;
}

算距離炸了 int,隊友不相信我的的最短路,罰時了兩發。

M - BpbBppbpBB

數滿足形狀的空白,然後判斷空白間的距離來計算數量。隊友寫的。

#include<bits/stdc++.h>
using namespace std;
#define ri int
#define MAXN 1010
#define pii pair< int,int >
#define fi first
#define se second

const int dx[]={0,0,0,1,1,1,1,2,2,2,2,3,3};
const int dy[]={0,0,1,-1,0,1,2,-1,0,1,2,0,1};
char s[MAXN];
int a[MAXN][MAXN],n,m;

inline bool jud(int x,int y)
{
  if(x-1<1 || x+4>n || y-2<1 || y+3>m) return 0;
  for(ri i=1;i<=12;i++) if(a[x+dx[i]][y+dy[i]]) return 0;
  int ret=0;
  for(ri i=x-1;i<=x+4;i++)
    for(ri j=y-2;j<=y+3;j++)
      ret+=(a[i][j]==0);
  return (ret==12);
}

int main()
{
  cin>>n>>m;
  for(ri i=1;i<=n;i++)
  {
    scanf("%s",s+1);
    for(ri j=1;j<=m;j++)
    {
      if(s[j]=='#') a[i][j]=1;
      else a[i][j]=0;
    }
  }
  vector< pii > v;
  for(ri i=1;i<=n;i++)
    for(ri j=1;j<=m;j++)
      if(!a[i][j]) 
        if(jud(i,j)) 
      {
        v.push_back(make_pair(i,j));
      }
  int ans1=0;
  for(auto i=v.begin();i!=v.end();++i)
  {
    int x1=(*i).fi,y1=(*i).se,x2,y2;
    for(auto j=i+1;j!=v.end();++j)
    {
      x2=(*j).fi,y2=(*j).se;
      if((x1==x2 && abs(y1-y2)==7) || (y1==y2 && abs(x1-x2)==7)) ++ans1;
    }
  }
  printf("%d %d",ans1,v.size()-ans1*2);
}

I - Barbecue

  • 初始爲迴文串,先手必敗
  • 長度爲 \(2\) 的串,先手必敗。
  • 更長的非迴文串,判斷兩邊分別刪掉一個字符是否爲迴文,都爲迴文,先手必敗,否則看長度減一的情況。

發現必勝必敗很好算。

#include <bits/stdc++.h>
#define N 1000001

int min(int x, int y) { return x < y ? x : y; }
int max(int x, int y) { return x > y ? x : y; }

std::string s;
int n, q, cnt, p[N << 1], ans[N];
char data[N << 1], *res[2] = {"Putata", "Budada"};

void qr() {
  data[0] = '~', data[cnt = 1] = '|';
  for (int i = 0, st = s.length(); i < st; ++i) {
    data[++cnt] = s[i], data[++cnt] = '|';
  }
}

bool is(int l, int r) {
  return p[2 * l + (r - l + 1) + 1] >= (r - l + 1);
}

int main() {
  scanf("%d %d", &n, &q);
  std::cin >> s;
  qr();
  for (int t = 1, r = 0, mid = 0; t <= cnt; ++t) {
    if (t <= r) p[t] = min(p[(mid << 1) - t], r - t + 1);
    while (data[t - p[t]] == data[t + p[t]]) ++p[t];
    if (p[t] + t > r) r = p[t] + t - 1, mid = t;
  }
  ans[1] = ans[2] = 1;
  for (int i = 3; i <= n; ++i) ans[i] = ans[i - 1] ^ 1;
  for (int i = 1, l, r; i <= q; ++i) {
    scanf("%d %d", &l, &r);
    if (r - l + 1 <= 2) puts("Budada");
    else {
      if (is(l - 1, r - 1) || (is(l - 1, r - 2) && is(l, r - 1))) puts("Budada");
      else puts(res[ans[r - l + 1]]);
    }
  }
  return 0;
}

被隊友忽悠寫了不熟悉的 \(manacher\),調了好久。

After

昨天和三個隊友 \(vp\) 了一場。

卡題了,還是簡單題,氣氛壓抑。

唉。多練!希望正式參賽別卡。

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