Codeforces Round #653 (Div. 3)(A, B, C, D, E1詳解)

Codeforces Round #653 (Div. 3)

Required Remainder

Thinking(binary search)

既然是找最大值問題,我又懶得去推式子,於是我直接就上了一個二分,二分寫法比結論稍微繁瑣了一點吧,但是還是挺好想的。

根據題意,我們的任務就是找到一個最大的數,滿足ans=kx+y<=nans = k * x + y <= n,於是我們就可以通過二分枚舉kk,來得到我們的答案。通過題目給定的x,y,zx, y, z的範圍,我們可以確定二分的區間最多不過0 190 ~ 1^9

Coding

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-7;

inline ll read() {
  ll f = 1, x = 0;
  char c = getchar();
  while(c < '0' || c > '9') {
    if(c == '-')  f = -1;
    c = getchar();
  }
  while(c >= '0' && c <= '9') {
    x = (x << 1) + (x << 3) + (48 ^ c);
    c = getchar();
  }
  return f * x;
}

const int N = 1e6 + 10;

char str[N];

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int _ = read();
  while(_--) {
      ll x = read(), y = read(), n = read();
      ll l = 0, r = 1e9 + 10;
      while(l < r) {
        ll mid = l + r + 1 >> 1;
        if(mid * x + y <= n)  l = mid;
        else r = mid - 1;
      }
      printf("%lld\n", l * x + y);
  }
  return 0;
}

Multiply by 2, divide by 6

Thinking

判斷能否通過0個或者多個乘二的操作,使數字變成6的倍數。我們想想6的兩個質因子2,32, 3,要想達到這個目的,對於初始的nn,只可能有這兩種質因子,否則我們一定達不到我們的目標。於是我們可以先對nn,進行2,32, 3的質因數提取,假設得到的22的因子個數是num2num233的因子個數是num3num3,因爲我們是同時消去2,32, 3因子的,並且只能增加或者不增加22的因子個數,所以只有當num2<=num3num2 <= num3時,才能保證我們可以消去所有的2,32, 3因子,最後變成11

Coding

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-7;

inline ll read() {
  ll f = 1, x = 0;
  char c = getchar();
  while(c < '0' || c > '9') {
    if(c == '-')  f = -1;
    c = getchar();
  }
  while(c >= '0' && c <= '9') {
    x = (x << 1) + (x << 3) + (48 ^ c);
    c = getchar();
  }
  return f * x;
}

const int N = 1e6 + 10;

char str[N];

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int _ = read();
  while(_--) {
    ll n = read();
    int num2 = 0, num3 = 0;
    while(n % 3 == 0) {
      n /= 3;
      num3++;
    }
    while(n % 2 == 0) {
      n /= 2;
      num2++;
    }
    //最後n不是1說明還存在其他的質因子。
    if(n != 1 || num2 > num3) puts("-1");
    else  printf("%d\n", num3 + num3 - num2);
  }
  return 0;
}

Move Brackets

Thinking(Stack)

我們先找到所有的符合匹配的括號,最後就只剩下一種非法的括號了,以這種形式存在)() (形成)))))((((()))))(((((這樣的排列,所以我們只需要將其後面的移到前面去,或者前面的移到後面去,任選一種進行操作,因此我們的花費將會是最後無法匹配的括號的對數,也就是棧中的元素的一半。

Coding

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-7;

inline ll read() {
  ll f = 1, x = 0;
  char c = getchar();
  while(c < '0' || c > '9') {
    if(c == '-')  f = -1;
    c = getchar();
  }
  while(c >= '0' && c <= '9') {
    x = (x << 1) + (x << 3) + (48 ^ c);
    c = getchar();
  }
  return f * x;
}

const int N = 1e6 + 10;

char str[N];

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int _; cin >> _;
  while(_--) {
    int n; cin >> n;
    stack<char> stk;
    for(int i = 1; i <= n; i++) {
      char temp;  cin >> temp;
      if(stk.empty() || stk.top() == temp || temp == '(')  stk.push(temp);
      else  stk.pop();
    }
    printf("%d\n", stk.size() / 2);
  }
  return 0;
}

Zero Remainder Array

Thinking

對於給定的序列,我們需要的就是x(modk)=(1,2k2,k1)x \pmod k = (1, 2 …… k - 2, k - 1),這樣的數,才能使我們的序列變成都是kk的倍數,假定k=4k = 4,數組中存在兩個數分別爲3,73, 7, 他們有一個共同點3(modk) =7(modk)3 \pmod k \ = 7 \pmod k,也就是說我們在x(modk)x \pmod k0>k10 -> k - 1,的一趟循環中,最多隻能使其中的一個數變成ai(modk)=0a_i \pmod k = 0,想必看到這裏應該就搞懂了這道題了,我們就是要找到ai(modk)a_i \pmod k後出現的次數最多的非零數,當有多個出現次數相同的數時我們取ai(modk)a_i \pmod k的最小值,因爲那個最小值一定是當xx足夠大的時候纔會滿足條件。

Coding

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-7;

inline ll read() {
  ll f = 1, x = 0;
  char c = getchar();
  while(c < '0' || c > '9') {
    if(c == '-')  f = -1;
    c = getchar();
  }
  while(c >= '0' && c <= '9') {
    x = (x << 1) + (x << 3) + (48 ^ c);
    c = getchar();
  }
  return f * x;
}

const int N = 2e5 + 10;

int a[N];

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int _ = read();
  while(_--) {
    int n = read(), k = read();
    for(int i = 1; i <= n; i++) {
      a[i] = read();
      a[i] %= k;
    }
    sort(a + 1, a + 1 + n, greater<int> ());
    int now_num = 1, ansn = a[1], num = 1;
    for(int i = 2; i <= n && a[i] != 0; i++) {
      if(a[i] == a[i - 1])  now_num++;
      else  now_num = 1;
      if(now_num >= num)  ansn = a[i], num = now_num;
    }
    if(ansn == 0){
      puts("0");
      continue;
    }
    // cout << num << " " << ansn << endl;
    printf("%lld\n", 1ll * k * (num - 1) + k - ansn + 1);
  }
  return 0;
}

Reading Books (easy version)

Thinking(Sort, greedy)

題意這裏就不說明了,對於給定的條件,我們要同時滿足AliceandBobAlice and Bob都要讀至少kk本書,所以我們可以指定一個策略,不管這本書是AliceorBobAlice or Bob喜歡,還是他們兩同時喜歡,我們都同時增加AliceandBobAlice and Bob的當前的書的數量,因此在之前我們就需要對書本分類AliceAlice喜歡的數組a,BobBob喜歡的數組b,兩個人都喜歡的數組c。接下來就時對這三個數組分別按照元素大小從小到大進行排序

當我們當前枚舉的ai+bj<=cka_i + b_j <= c_k時我們顯然貪心的選擇ai,bja_i, b_j這兩本書,所以我們的總花費將會變成ans+=ai+bjans += a_i + b_j,否則的話我們將會選擇ckc_k,花費將變成ans+=ckans += c_k

當我們第一個點枚舉完了後,大致存在三種情況aa不可選,bb不可選,cc不可選。

所以接下來的枚舉我們必須分類討論了當aba || b,不可選的時候,我們要達到條件只能通過選擇cc來進行。否則的話我們就只能選擇a,ba, b兩個組合選取了。

Code

#include <bits/stdc++.h>
#define mp make_pair
// #define pb push_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-7;

inline ll read() {
  ll f = 1, x = 0;
  char c = getchar();
  while(c < '0' || c > '9') {
    if(c == '-')  f = -1;
    c = getchar();
  }
  while(c >= '0' && c <= '9') {
    x = (x << 1) + (x << 3) + (48 ^ c);
    c = getchar();
  }
  return f * x;
}

const int N = 2e5 + 10;

struct Node {
  int value, fa, fb;
  void input() {
    value = read(), fa = read(), fb = read();
  }
  void out() {
    printf("%d %d %d\n", value, fa, fb);
  }
  bool operator < (const Node & t) const {
    return value < t.value;
  }
}a[N], b[N], c[N], in;
//結構體就是數組的用處,不用管。是我自己一開始思路想的有點複雜,然後就寫了這麼一個結構體。

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int n = read(), k = read(), na = 0, nb = 0, nc = 0;
  for(int i = 1; i <= n; i++) {
    in.input();
    if(in.fa && in.fb)  c[++nc] = in;
    else if(in.fa)  a[++na] = in;
    else if(in.fb)  b[++nb] = in;
    //一定要注意特判 0 0的情況。
  }
  // cout << na << " " << nb << " " << nc << endl;
  sort(a + 1, a + 1 + na);
  sort(b + 1, b + 1 + nb);
  sort(c + 1, c + 1 + nc);
  int pa = 1, pb = 1, pc = 1, flag = 0;
  int numa = 0, numb = 0;
  ll ans = 0;
  while(pa <= na && pb <= nb && pc <= nc) {
    if(a[pa].value + b[pb].value <= c[pc].value) {
      ans += a[pa].value + b[pb].value;
      pa++, pb++;
    }
    else {
      ans += c[pc].value;
      pc++;
    }
    numa++, numb++;
    if(numa >= k && numb >= k) {
      flag = 1;
      break;
    }
  }
  // cout << ans << " " << numa << " " << numb << endl;
  if(flag) {
    printf("%lld\n", ans);
    return 0;
  }
  if(pa > na || pb > nb) {
    while(pc <= nc) {
      ans += c[pc].value;
      pc++;
      numa++, numb++;
      if(numa >= k && numb >= k) {
        flag = 1;
        break;
      }
    }
  }
  else {
    while(pa <= na && pb <= nb) {
      ans += a[pa].value + b[pb].value;
      pa++, pb++;
      numa++, numb++;
      if(numa >= k && numb >= k) {
        flag = 1;
        break;
      }
    }
  }
  if(flag) {
    printf("%lld\n", ans);
    return 0;
  }
  puts("-1");
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章