「题解」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\) 了一场。

卡题了,还是简单题,气氛压抑。

唉。多练!希望正式参赛别卡。

posted @ 2024-04-15 16:27  yu__xuan  阅读(101)  评论(0编辑  收藏  举报