1. 程式人生 > >2017, X Samara Regional Intercollegiate Programming Contest 題解

2017, X Samara Regional Intercollegiate Programming Contest 題解

題目連結

首先將每一個括號匹配串進行一次縮減,即串內能匹配掉的就匹配掉,每個串會變成連續的$y$個右括號+連續$z$個左括號。

我們把縮減後的串分成四類:

第一類:只有左括號

第二類:左右括號都有,且$z$大於等於$y$

第三類:左右括號都有,且$z$小於$y$

第四類:只有右括號

類與類之間肯定是按第$1$,$2$,$3$,$4$類的順序放置。

第一類內部和第四類內部可以隨便放。第二類的放置順序也很容易想。

問題出在第三類放置的順序,按照$z$大的先放是正確方式,其餘都能舉出反例。

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

const int maxn = 2e5 + 10;

struct X {
  int y, z;
  int id, tp;
}s[maxn];
int n;
char t[maxn];

bool cmp(const X& a, const X& b) {
  if(a.tp != b.tp) return a.tp < b.tp;
  if(a.tp == 2) {
    if(a.y != b.y) return a.y < b.y;
    return a.z > b.z;
  } else if(a.tp == 3) {
    return a.z > b.z;
  } else {
    return 0;
  }
}

int main() {
  scanf("%d", &n);
  for(int i = 0; i < n; i ++) {
    scanf("%s", t);
    int z = 0, y = 0;
    for(int j = 0; t[j]; j ++) {
      if(t[j] == '(') z ++;
      else {
        if(z) z --;
        else y ++;
      }
    }
    s[i].y = y;
    s[i].z = z;
    s[i].id = i;
    /* ))) y個 ((( z個 */
    if(y + z == 0) s[i].tp = 0;
    else if(y == 0 && z != 0) s[i].tp = 1;
    else if(y != 0 && z == 0) s[i].tp = 4;
    else if(z - y >= 0) s[i].tp = 2;
    else s[i].tp = 3;
  }
  sort(s, s + n, cmp);
  int sum = 0;
  int fail = 0;
  for(int i = 0; i < n; i ++) {
    sum = sum - s[i].y;
    if(sum < 0) {
      fail = 1;
      break;
    }
    sum = sum + s[i].z;
  }
  if(fail || sum != 0) {
    printf("NO\n");
  } else {
    printf("YES\n");
    for(int i = 0; i < n; i ++) {
      printf("%d", s[i].id + 1);
      if(i < n - 1) printf(" ");
      else printf("\n");
    }
  }
  return 0;
}

/*
 4
 (((((
 )))))((
 ))(
 )
 
 y大的先放會無解
 4
 (((((
 ))))(
 )))((
 )

 */

先找出有多少個區間是happiness,接下里分情況討論:

如果沒有:要注意交換後可能出現happiness。

如果有$1$個:那麼可以有多少方式,例如交換第一個和第二個。

如果有$2$個:可以有多種方式,例如第一個區間的第一個字母和第二個區間的第二個字母交換。

如果大於等於$3$個:無解。

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

const int N = 4e5 + 10;
char S[N], T[N] = "happiness";
int nx[N];
int slen, tlen;
vector<int > pos;

void getNext()
{
  int j, k;
  j = 0; k = -1; nx[0] = -1;
  while(j < tlen)
    if(k == -1 || T[j] == T[k])
      nx[++j] = ++k;
    else
      k = nx[k];
}

int KMP_Count()
{
  int ans = 0;
  int i, j = 0;
  
  if(slen == 1 && tlen == 1)
  {
    if(S[0] == T[0])
      return 1;
    else
      return 0;
  }
  getNext();
  for(i = 0; i < slen; i++)
  {
    while(j > 0 && S[i] != T[j])
      j = nx[j];
    if(S[i] == T[j])
      j++;
    if(j == tlen)
    {
      ans++;
      pos.push_back(i);
      j = nx[j];
    }
  }
  return ans;
}

int main() {
  srand(time(NULL));
  scanf("%s", S);
  slen = strlen(S);
  tlen = strlen(T);
  KMP_Count();
  if(slen < 9) {
    printf("YES\n");
    printf("1 2\n");
    return 0;
  }
  if(pos.size() == 0) {
    printf("YES\n");
    int x, y;
    while(1) {
      x = rand() % slen;
      y = rand() % slen;
      if(x == y) continue;
      swap(S[x], S[y]);
      pos.clear();
      KMP_Count();
      if(pos.size() == 0) break;
      swap(S[x], S[y]);
    }
    printf("%d %d\n", x + 1, y + 1);
  } else if(pos.size() == 1) {
    // [pos[0] - 8 ,pos[0]]
    printf("YES\n");
    int x = 0, y = 1;
    printf("%d %d\n", x + pos[0] - 8 + 1, y + pos[0] - 8 + 1);
  } else if(pos.size() == 2) {
    int x = 0, y = 1;
    printf("YES\n");
    printf("%d %d\n", x + pos[0] - 8 + 1, y + pos[1] - 8 + 1);
  } else {
    printf("NO\n");
  }
  return 0;
}

留。

#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
int main()
{
    long long a,b,c,n,m;
    while(~scanf("%lld%lld%lld",&a,&b,&c))
    {
        scanf("%lld%lld",&n,&m);
        long long t1,t2;
        if(a+c<=n&&b<=m)t1=a+b+c;
        else if(n>=m)
        {
            if(a+c<=n&&b>m)
                t1=m;
            else if(a+c>n&&b>m)
                t1=m;
            else if(a+c>n&&b<=m)
                t1=n;
        }
        else
        {
            if(a+c<=n&&b>m)
                t1=m;
            else if(a+c>n&&b>m)
                t1=n;
            else if(a+c>n&&b<=m)
                t1=n;
        }
        if(a<=n&&b+c<=m)t2=a+b+c;
        else if(n>=m)
        {
            if(a<=n&&b+c>m)t2=m;
            else if(a>n&&b+c>m)t2=m;
            else if(a>n&&b+c<=m)t2=n;
        }
        else
        {
            if(a<=n&&b+c>m)t2=m;
            else if(a>n&&b+c>m)t2=n;
            else if(a>n&&b+c<=m)t2=n;
        }
        printf("%lld\n",min(t1,t2));
    }
    return 0;
}

如果所有的數字的$gcd$是$x$的約數,則可行,否則不可行。

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

const int maxn = 2e5 + 10;
int n, x;

int gcd(int a, int b) {
  if(b == 0) return a;
  return gcd(b, a % b);
}

int main() {
  scanf("%d%d", &n, &x);
  int g;
  for(int i = 1; i <= n; i ++) {
    int y;
    scanf("%d", &y);
    if(i == 1) g = y;
    else g = gcd(g, y);
  }
  if(abs(x) % g) printf("NO\n");
  else printf("YES\n");
  return 0;
}

寶石和跳躍機合起來排序,最左邊跳躍機左邊那些寶石必須來回走一次,最右邊跳躍機右邊的那些寶石必須來回走一次。

然後計算每相鄰兩個跳躍機之間的寶石怎麼取費用最小,列舉一下哪個從寶石斷開就可以了。

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

const int maxn = 4e5 + 10;
struct X {
  int tp;
  long long x;
}s[maxn];
int n, m;

bool cmp(const X& a, const X& b) {
  if(a.x != b.x) return a.x < b.x;
  return a.tp > b.tp;
}

long long work(int L, int R) {
 // cout << L << " - " << R << endl;
  if(R - L < 2) return 0LL;
  long long res = s[R].x - s[L].x;
  for(int i = L; i <= R - 1; i ++) {
    long long sum = (s[i].x - s[L].x) * 2LL;
    sum += (s[R].x - s[i + 1].x) * 2LL;
    res = min(res, sum);
  }
  return res;
}

int main() {
  scanf("%d%d", &n, &m);
  for(int i = 0; i < n; i ++) {
    scanf("%lld", &s[i].x);
    s[i].tp = 0;
  }
  for(int i = n; i < n + m; i ++) {
    scanf("%lld", &s[i].x);
    s[i].tp = 1;
  }
 // cout << "debug" << endl;
  sort(s, s + n + m, cmp);
  int pre = -1;
  for(int i = 0; i < n + m; i ++) {
    if(s[i].tp == 0) {
      pre = i;
      break;
    }
  }
  long long ans = 0;
  ans = abs(s[pre].x - s[0].x) * 2LL;
  
  while(1) {
    int now = -1;
    for(int i = pre + 1; i < n + m; i ++) {
      if(s[i].tp == 0) {
        now = i;
        break;
      }
    }
    if(now == -1) {
      ans = ans + abs(s[n + m - 1].x - s[pre].x) * 2LL;
      break;
    }
    // [pre, now]
    ans = ans + work(pre, now);
    pre = now;
  }
  printf("%lld\n", ans);
  return 0;
}

這是我做的第一個互動題。我是隨機做法,交了很多次,有一次是通過的,其餘全是答案錯誤。

具體想法是這樣的:

假設我們知道其中一個可用的是哪個,那麼我們就可以找出所有可用的。

然後我就去猜哪個是可用的,然後驗證看看是不是滿足條件。驗證的時候就是看不可用的數量是否嚴格小於一半。

因為題目要求在$4n$次出解,因此我們至少可以猜$4$次,中一次就可以了,而且每次猜對的概率約等於$1/2$,再加一點剪枝,可以使得猜的次數增加,具體可以看程式碼。

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

const int maxn = 100010;
int n;
vector<int> ans;
int f[maxn];
char s1[maxn], s2[maxn];

int main() {
  srand(time(NULL));
  scanf("%d", &n);
  int h = (n - 1) / 2;
  for(int t = 0; t < n; t ++) {
    ans.clear();
    int x;
    int y = rand() % (n - t) + 1;
    int num = 0;
    for(int i = 1; i <= n; i ++) {
      if(f[i]) continue;
      num ++;
      if(num == y) {
        x = i;
        break;
      }
    }
    f[x] = 1;
    int fail = 0;
    for(int i = 1; i <= n; i ++) {
      if(i == x) {
        ans.push_back(i);
        continue;
      }
      printf("? %d %d\n", x, i);
      fflush(stdout);
      scanf("%s%s", s1, s2);
      if(s1[0] == '+' && s2[0] == '+') {
        ans.push_back(i);
      }
      if(i - ans.size() > h) {
        fail = 1;
        break;
      }
    }
    if(n - ans.size() > h) fail = 1;
    if(fail == 0) break;
  }
  printf("! %d", ans.size());
  sort(ans.begin(), ans.end());
  for(int i = 0; i < ans.size(); i ++) {
    printf(" %d", ans[i]);
  }
  printf("\n");
  fflush(stdout);
  return 0;
}

模擬一下就可以了。

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

const int maxn = 2e5 + 10;
string name[maxn];
int n, m;

int p[maxn], q[maxn];

int main() {
  scanf("%d", &n);
  for(int i = 1; i <= n; i ++) {
    cin >> name[i];
    q[i] = i;
  }
  int m;
  scanf("%d", &m);
  int x, y;
  for(int i = 1; i <= m; i ++) {
    
    scanf("%d%d", &x, &y);
    p[x] = p[y] + 1;
    q[x] = q[y];
  }
  while(p[1]) {
    printf("I_love_");
    p[1] --;
  }
  cout << name[q[1]] << endl;
  return 0;
}

找到一個最大值的位置,最大值的位置一定要被刪掉,不然留下個最值不會讓答案更優,接下來有三種策略:

第一種:刪掉最大值所在行和列。

第二種:刪掉最大值所在的行,再刪除剩餘矩陣最大值所在的列。

第三種:刪掉最大值所在的列,再刪除剩餘矩陣最大值所在的行。

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

const int maxn = 1010;
int n, m;
int a[maxn][maxn];
vector<int> mx;
vector<int> r;
vector<int> c;

int work(int x, int y) {
  int res = 0;
  for(int i = 1; i <= n; i ++) {
    for(int j = 1; j <= m; j ++) {
      if(i == x || j == y) continue;
      res = max(res, a[i][j]);
    }
  }
  return res;
}

int main() {
  scanf("%d%d", &n, &m);
  int mr = 1, mc = 1, Max = a[1][1];
  for(int i = 1; i <= n; i ++) {
    for(int j = 1; j <= m; j ++) {
      scanf("%d", &a[i][j]);
      if(a[i][j] > Max) {
        Max = a[i][j];
        mr = i;
        mc = j;
      }
    }
  }
  
  for(int i = 0; i < 3; i ++) {
    mx.push_back(0);
    r.push_back(0);
    c.push_back(0);
  }
  
  
  // 刪最大值所在行列
  r[0] = mr;
  c[0] = mc;
  mx[0] = work(mr, mc);
  
  r[1] = mr;
  // 先刪最大值所在行,再刪最大值所在列
  int kk = work(mr, 0);
  for(int i = 1; i <= n; i ++) {
    if(i == mr) continue;
    for(int j = 1; j <= m; j ++) {
      if(a[i][j] == kk) {
        c[1] = j;
      }
    }
  }
  mx[1] = work(r[1], c[1]);
  
  c[2] = mc;
  // 先刪最大值所在列,再刪最大值所在行
  int qq = work(0, mc);
  for(int i = 1; i <= n; i ++) {
    for(int j = 1; j <= m; j ++) {
      if(j == mc) continue;
      if(a[i][j] == qq) {
        r[2] = i;
      }
    }
  }
  mx[2] = work(r[2], c[2]);
  
  int ans = 1e9 + 7;
  int idx = 0;
  for(int i = 0; i < 3; i ++) {
    if(mx[i] < ans) {
      ans = mx[i];
      idx = i;
    }
  }
  
  printf("%d %d\n", r[idx], c[idx]);
  
  return 0;
}

一開始的做法:檢查每一行的和是否相同,每一列的和是否相同,然後隨機選擇$n$個點看是否相同,但是一直答案錯誤。後來意識到一個問題,假設資料是$1000*1000$的矩陣,$C$矩陣和$A*B$矩陣的差別僅僅是其中的一個$2*2$子矩陣,這時候,可以構造出資料使得每一行每一列的和都相同,隨機選擇$n$個點大概率也是相同的,所以檢測不出來。

後來我檢測了每一行的$hash$值,即和字串$hash$做法一樣,每一行當做一個字串,$A*B$矩陣每一行的hash值是可以$O(n^2)$得到的,這樣就AC了。

看到大佬都是隨機構造一個$1*n$的$X$矩陣做的,只要檢查$X*A*B$是否等於$X*C$即可,膜。

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

long long mod = 1e9 + 7;
const int maxn = 1100;
long long a[3][maxn][maxn];
long long r[3][maxn][maxn];
long long base = 131LL;
int n;

int main() {
  scanf("%d", &n);
  for(int t = 0; t < 3; t ++) {
    for(int i = 1; i <= n; i ++) {
      for(int j = 1; j <= n; j ++) {
        scanf("%lld", &a[t][i][j]);
        r[t][i][j] = (r[t][i][j - 1] * base % mod + a[t][i][j]) % mod;
      }
    }
  }
  int fail = 0;
  
  // 檢查每一行的 hash 值
  for(int i = 1; i <= n; i ++) {
    long long A = 0;
    for(int k = 1; k <= n; k ++) {
      long long B = a[0][i][k] * r[1][k][n] % mod;
      A = (A + B) % mod;
    }
    if(A != r[2][i][n]) fail = 1;
  }
  
  if(fail) printf("NO\n");
  else printf("YES\n");
  return 0;
}

還在做。

區間按右端點排序,然後就可以$dp$了,中間要二分一個位置$p$,只有位置$[1,p]$是可以轉移到位置$i$的狀態的。

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

const int maxn = 2e5 + 10;
struct X {
  int id;
  int L, R;
  long long c;
}s[maxn];
int n;

int pre[maxn];
int wei[maxn];
long long fen[maxn];
long long tim[maxn];

vector<int> use;

bool cmp(const X &a, const X &b) {
  return a.R < b.R;
}

void up(long long x, long long y, int idx) {
  if(x > fen[idx - 1] || (x == fen[idx - 1] && y < tim[idx - 1])) {
    fen[idx] = x;
    tim[idx] = y;
    wei[idx] = idx;
  } else {
    fen[idx] = fen[idx - 1];
    tim[idx] = tim[idx - 1];
    wei[idx] = wei[idx - 1];
  }
}

int main() {
  scanf("%d", &n);
  for(int i = 1; i <= n; i ++) {
    pre[i] = -1;
    scanf("%d%d%lld", &s[i].L, &s[i].R, &s[i].c);
    s[i].id = i;
  }
  sort(s + 1, s + 1 + n, cmp);
  for(int i = 1; i <= n; i ++) {
    int L = 1, R = i - 1, pos = -1;
    while(L <= R) {
      int mid = (L + R) / 2;
      if(s[mid].R > s[i].L) R = mid - 1;
      else pos = mid, L = mid + 1;
    }
    if(pos == -1) {
      long long now_fen = s[i].c;
      long long now_tim = s[i].R - s[i].L;
      if(i == 1) {
        wei[i] = 1;
        fen[i] = now_fen;
        tim[i] = now_tim;
      } else {
        up(now_fen, now_tim, i);
      }
    } else {
      long long now_fen = s[i].c + fen[pos];
      long long now_tim = s[i].R - s[i].L + tim[pos];
      pre[i] = wei[pos];
      up(now_fen, now_tim, i);
    }
  }
  
  long long ans_fen = 0;
  long long ans_tim = 0;
  for(int i = 1; i <= n; i ++) {
    if(fen[i] > ans_fen) {
      ans_fen = fen[i];
      ans_tim = tim[i];
    } else if(fen[i] == ans_fen) {
      ans_tim = min(ans_tim, tim[i]);
    }
  }
  
  int last = -1;
  for(int i = 1; i <= n; i ++) {
    if(fen[i] == ans_fen && tim[i] == ans_tim) {
      last = i;
      break;
    }
  }
  
  while(last != -1) {
    use.push_back(last);
    last = pre[last];
  }
  
  for(int i = 0; i < use.size(); i ++) {
    use[i] = s[use[i]].id;
  }
  sort(use.begin(), use.end());

  printf("%d %lld %lld\n", use.size(), ans_fen, ans_tim);
  for(int i = 0; i < use.size(); i ++) {
    printf("%d", use[i]);
    if(i < use.size() - 1) printf(" ");
    else printf("\n");
  }
  return 0;
}

區間按$L$排序,$L$相同的只保留$R$最大的那個。

然後一個一個區間加入,加入第$i$個區間的時候,比$Li$小的那些位置不需要考慮了,概率肯定是100%。

只需考慮比$Li$大的那些位置,畫畫圖可以發現是在維護一個斜率遞減的圖形。

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

const double height = 2e9;
const double eps = 1e-8;
const int maxn = 2e5 + 10;
struct X {
  double L, R;
  double nowL, nowR;
  int id;
}s[maxn];
stack<int> st;
vector<int> vec;
int n;

bool cmp(const X& a, const X& b) {
  if(fabs(a.L - b.L) < eps) return a.R > b.R;
  return a.L < b.L;
}

double work(double x, int id) {
  return (s[id].R - x) * height / (s[id].R - s[id].L);
}

int main() {
  scanf("%d", &n);
  for(int i = 0; i < n; i ++) {
    scanf("%lf%lf", &s[i].L, &s[i].R);
    s[i].nowL = s[i].L;
    s[i].nowR = s[i].R;
    s[i].id = i + 1;
  }
  sort(s, s + n, cmp);
  for(int i = 0; i < n; i ++) {
    if(st.empty()) {
      st.push(i);
      continue;
    }
    if(fabs(s[i].L - s[i - 1].L) < eps) {
      continue;
    }
    while(!st.empty()) {
      int id = st.top();
      double xL = max(s[id].nowL, s[i].nowL);
      double xR = min(s[id].nowR, s[i].nowR);
      if(xR < xL) {
        st.pop();
        continue;
      }
      if(work(xL, id) <= work(xL, i) + eps
         && work(xR, id) <= work(xR, i) + eps) {
        st.pop();
      } else {
        double left = xL, right = xR, pos;
        int limit = 50;
        while(limit --) {
          pos = (left + right) / 2;
          if(work(pos, id) < work(pos, i)) left = pos;
          else right = pos;
        }
        s[i].nowR = pos;
        s[id].nowL = pos;
        break;
      }
    }
    st.push(i);
  }
  while(!st.empty()) {
    vec.push_back(st.top());
    st.pop();
  }
  
  int Q;
  scanf("%d", &Q);
  while(Q --) {
    double x;
    scanf("%lf", &x);
    if(x <= s[vec[0]].nowL + eps) {
      printf("%d\n", s[vec[0]].id);
      continue;
    }
    int left = 0, right = vec.size() - 1, ans = -1;
    while(left <= right) {
      int mid = (left + right) / 2;
      if(x < s[vec[mid]].nowL) right = mid - 1;
      else ans = mid, left = mid + 1;
    }
    if(ans == -1) ans = 0;
    printf("%d\n", s[vec[ans]].id);
  }
  
  return 0;
}

每次讓一個$a_i$為$0$的分配給一個$a_j$不為$0$的人,然後$a_j$就可以減去$1$,一直這樣操作。

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

const int maxn = 200000 + 10;
int n;
int a[maxn];
queue<int> q;
int ans[maxn];

int main() {
  scanf("%d", &n);
  int now = -1;
  for(int i = 1; i <= n; i ++) {
    scanf("%d", &a[i]);
    if(a[i]) now = i;
    if(a[i] == 0) q.push(i);
  }
  if(now == -1) {
    printf("YES\n");
    return 0;
  }
  int fail = 0;
  while(now) {
    if(q.empty()) {
      fail = 1;
      break;
    }
    int f = q.front();
    q.pop();
    ans[f] = now;
    a[now] --;
    if(a[now] == 0) {
      q.push(now);
      now --;
    }
  }
  for(int i = 1; i <= n; i ++) {
    if(a[i]) fail = 1;
  }
  if(fail) printf("NO\n");
  else {
    printf("YES\n");
    for(int i = n; i > 1; i --) {
      if(ans[i])
      printf("%d %d\n", ans[i], i);
    }
  }
  return 0;
}

相關推薦

2017, X Samara Regional Intercollegiate Programming Contest 題解

【題目連結】 首先將每一個括號匹配串進行一次縮減,即串內能匹配掉的就匹配掉,每個串會變成連續的$y$個右括號+連續$z$個左括號。 我們把縮減後的串分成四類: 第一類:只有左括號 第二類:左右括號都有,且$z$大於等於$y$ 第三類:左右括號都有,且$z$小於$y$ 第四類:只有右括號

Codeforces Gym100971 C.Triangles-組三角形 (IX Samara Regional Intercollegiate Programming Contest Russia, Samara, March 13)

def img triangle ace ces return cst \n mage 這個題就是組三角形,從給出的數組裏任選兩個和未知的邊組三角形。 任意兩邊之和大於第三邊,記住這個就可以了。 代碼: 1 #include<c

2018, XI Samara Regional Intercollegiate Programming Contest J題-Parallelograms

題意:若干個棍子,求能最多組成多少個平行四邊形分析:統計不同長度的棍子數目,用一個變數tot加上每個長度棍子數目/2, 最後輸出tot/2每個長度的棍子要在一個平行四邊形內使用兩根,最後還要任意2組的長度的棍子搭配~一開始以為可以不同長度的棍子拼接成一條邊使用,就思考了好久沒

2018, XI Samara Regional Intercollegiate Programming Contest H題- Safe Path

題意:問你能否從起始點到達出發點。注意,在地圖的一些地區有怪獸,只要怪獸能在d步內到達你現在的位置,你會被立刻殺死。。分析:BFS裸題,注意,N*M是2e5大小,把地圖進行壓縮一下~程式碼如下:#include <cstdio> #include <cstr

2015 ACM Amman Collegiate Programming Contest 題解

#include <bits/stdc++.h> using namespace std; const int N = 2e5 + 10; int dfn[N],low[N],dfs_clock; int n, m; int h[N], to[N], nx[N], sz;

2013-2014 ACM-ICPC Brazil Subregional Programming Contest 題解

【題目連結】 這場比賽題面英文都好長... ... 模擬。 #include <bits/stdc++.h> using namespace std; int main() { int a,b,c; cin>>a>>b>>

2019.04.11 第四次訓練 【 2017 United Kingdom and Ireland Programming Contest

dom href 概率 AMM ref ces 鏈接 題目 bsp 題目鏈接: https://codeforces.com/gym/101606 A: ? B: C: ? D: ? E: ? F: 概率dp G: H: I: ? J:

2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889

val bool b- truct 之前 排序 數位dp pen swap 挺有意思的一套題,題也沒有啥毒瘤了,本來是隊切的結果種種原因大家全掛機了。 只補了百人題,一共7個,其他的暫時先不補了,,也不會嘛qwq H:簽到 1 #include <bits/st

2017-2018 ACM-ICPC Latin American Regional Programming Contest

pdf 反轉 enc pin rac alt target 不同的 暴力 題面pdfhttps://codeforc.es/gym/101889/attachments/download/7471/statements-2017-latam-regional.pdf zyn

2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)(蒟蒻解題版)

http://codeforces.com/gym/101669/attachments 蒟蒻只討論四個題。(蒟蒻也覺得這樣不好,但是現在蒟蒻實力有限並且暫時沒有經歷更加深入的研究這種東西,等蒟蒻有時

2017 JUST Programming Contest 2.0 題解

【題目連結】 首先,$n>m$或$k>m$或$k>n$就無解。 設$p = \frac{A}{B}$,$ans = C_{n - 1}^{k - 1}{\left( {\frac{A}{B}} \right)^{k}}{\left( {\frac{B-A}{B}} \righ

2016-2017 ACM Central Region of Russia Quarterfinal Programming Contest BHanoi tower

ssi fin rdquo main \n n) src pro turn B Hanoi tower It has become a good tradition to solve the “Hanoi tower” puzzle at prog

The North American Invitational Programming Contest 2017 題目

data reverse eric gin b+ order logs mat bottom NAIPC 2017 Yin and Yang Stones 75.39% 1000ms 262144K A mysterious cir

The 15th Zhejiang Provincial Collegiate Programming Contest(部分題解

begin iter 一個數 ons opera cst style string += ZOJ 4024 Peak 題意 給出n和n個數,判斷該數列是否是凸形的。 解題思路 從前往後第一對逆序數,和從後往前第一隊逆序數,如果都非零而且相鄰,證明該數組是凸形的。 代碼

2017 Benelux Algorithm Programming Contest (BAPC 17)

地址 Rank Solved A B C D E F G H I J K L M 41/255 9/13 O .

【AtCoder】Dwango Programming Contest V題解

tco first rotation ram tmp pre 證明 必須 隊列 A - Thumbnail 根據題意寫代碼 #include <bits/stdc++.h> #define fi first #define se second #define p

The 2016 ACM-ICPC Asia Dalian Regional Contest---題解

 題意: 思路:題意真是**了,好不容易才猜對了題意。。是要判M條件是否矛盾。。但是一直讀的題意理解的都是不用判,, 知道題意,就簡單了,可以用二分圖染色,可以2-sat,,那我就比較厲害了,,我啥都沒有,一個dfs隨便搞搞,記錄下顏色,就A了,可怕的是猜題意猜了

2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)(solve7/11)

B題 題意:給你n個人的第一棒的速度和其他棒的速度,然後讓你輸出最快的那個組合,輸出時間和人。 思想:模擬 D題 題意:給你n個01串代表每個人的特徵,現在讓你求一個和他們長度相等但是和他們相似度最對的那個串。 思想:考慮最短路問題,將每個串拆出來k個差一位的子

2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017) 部分題/平衡樹/最小環/思路bfs

交題地址 難度按照順序遞增 J - Judging Moose 隊友敲的 #include <iostream> #include <cstdio> using namespace std; int main() {

2017-2018 ACM-ICPC Nordic ——Problem G 。Galactic Collegiate Programming Contest

Time limit: 6  secondsPicture by GuillaumePreat on Pixabay, cc0One hundred years from now, in 2117, the InternationalCollegiate Programmi