首页 > 其他分享 >Educational Codeforces Round 137 (Rated for Div. 2)题解

Educational Codeforces Round 137 (Rated for Div. 2)题解

时间:2022-10-18 18:56:32浏览次数:85  
标签:Educational Rated int 题解 ll read while dp getchar

比赛链接

A. Password

大水题,求个组合数就水掉了。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long

template <class T>
inline void read(T& a){
	T x = 0, s = 1;
	char c = getchar();
	while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
	a = x * s;
	return ;
}

vector <int> a; 
int fac[N];

void prepare(){
  fac[0] = fac[1] = 1; 
  for(int i = 1; i <= 10; i++)
    fac[i] = fac[i-1] * i;
  return ; 
}

int C(int a, int b){
  return fac[b] / (fac[a] * fac[b-a]); 
}

int main(){
  // freopen("hh.txt", "r", stdin); 
  int T; read(T);
  prepare(); 
  while(T--){
    // a.clear(); 
    int n; read(n);
    for(int i = 1; i <= n; i++){
      int x; read(x); 
    }

    cout << C(2, 10 - n) * 6 << endl; 

  }
  return 0;
}

B. Permutation Value

大水题。首先可以知道小的数字在一个排列中是不可缺少的。所以把小数字尽量放远一点即可。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long

template <class T>
inline void read(T& a){
	T x = 0, s = 1;
	char c = getchar();
	while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
	a = x * s;
	return ;
}

int ans[N]; 

int main(){
  // freopen("hh.txt", "r", stdin); 
  int T;read(T);
  while(T--){
    memset(ans, 0, sizeof(ans)); 
    int n; read(n);
    int tot = 0;
    int p = 1;
    int dis = 0; 
    for(int i = 1; i <= n; i++){
      ans[p] = i; 
      if(i % 2 == 0) p = dis + 1; 
      else p = n - dis, dis++; 
    }
    for(int i = 1; i <= n; i++){
      printf("%d ", ans[i]); 
    }
    cout << endl; 
  }
  return 0;
}

C. Save the Magazines

相对没那么水。设 \(dp\) 数组 \(dp_{i,0/1}\) 表示第 \(i\) 件物品为止,是否转移到前一个物品,情况下的最大值。公式见代码。注意讨论是否可以转移到前一个物品以及前提条件。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long

template <class T>
inline void read(T& a){
	T x = 0, s = 1;
	char c = getchar();
	while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
	a = x * s;
	return ;
}

int n;
char s[N]; 
int a[N]; 
int dp[N][2]; 

int main(){
  // freopen("hh.txt", "r", stdin); 
  int T; read(T);
  while(T--){
    // memset(dp, 0, sizeof(dp)); 
    read(n);
    scanf("%s", s + 1); 
    for(int i = 1; i <= n; i++) read(a[i]);

    for(int i = 1; i <= n; i++){
      if(s[i] == '1'){
        if(s[i-1] == '1') dp[i][1] = dp[i-1][1] + a[i-1]; 
        else dp[i][1] = dp[i-1][0] + a[i-1]; 
        dp[i][0] = max(dp[i-1][0], dp[i-1][1]) + a[i]; 
      }
      else{
        dp[i][1] = -1e9; 
        dp[i][0] = max(dp[i-1][0], dp[i-1][1]); 
      }
    }
    cout << max(dp[n][0], dp[n][1]) << endl; 
  }
  return 0;
}

D. Problem with Random Tests

本次比赛争议很大的一道题。由于全是随机数据,难度大大降低。首先容易想到,

可以贪心找到以 \(1\) 开头的一个长串,这样肯定可以保证结果尽量大。然后考虑寻找第二个串来跟他 \(or\) 一下。由于纯随机数据,复杂度期望 \(O(logN)\),很难卡掉,直接一个个暴力比较即可。

(这道题使用 string 会比较好写。本人比赛时太傻了,使用了数组。。。。)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long

template <class T>
inline void read(T& a){
	T x = 0, s = 1;
	char c = getchar();
	while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
	a = x * s;
	return ;
}

int n;
char t[N]; 
int s[N];
int tmp[N]; 
int ans[N];  
int m; 

bool check(int *a, int *b, int n){  // 检查 a 是否大于等于 b
  for(int i = 1; i <= n; i++){
    if(a[i] < b[i]) return 0; 
    if(a[i] > b[i]) return 1; 
    if(a[i] == b[i]) continue; 
  }
  return 1; 
}

int main(){
  // freopen("hh.txt", "r", stdin); 
  read(m);
  scanf("%s", t + 1);
  int p = -1; 
  for(int i = 1; i <= m; i++)
    if(t[i] == '1'){
      p = i;
      break; 
    }
  if(p == -1){
    cout << 0 << endl;
    return 0; 
  }
  n = m - p + 1; // 当前串的总长度
  int id = 0; 
  for(int i = p; i <= m; i++){
    s[++id] = t[i] - '0'; // 第一个串
  }

  for(int i = 1; i <= n; i++){
    if(s[i] == 0){
      p = i;
      break; 
    }
  }
  memcpy(ans, s, sizeof(ans)); 

  int len = n - p + 1;  // 小串的长度
  for(int i = 1; i + len <= n; i++){   // i: 小船的头
    memcpy(tmp, s, sizeof(tmp));   // 存一个副本
    if(s[i] != 1) continue; 
    for(int j = p, now = 0; j <= n && now < len; j++, now++){  
      tmp[j] |= s[i+now];  
    }
    if(check(tmp, ans, n)) memcpy(ans, tmp, sizeof(ans)); 
  }
  for(int i = 1; i <= n; i++)
    printf("%d", ans[i]); 
  //未完待续
  return 0;
}

E. FTL

本蒟蒻到 \(E\) 题便有些吃力了。考虑 \(dp\)。设 \(dp_x\) 表示造成 \(x\) 伤害所需要的最小时间。 考虑到若将剩余血量设为状态,可能出现负数,造成下标问题,故将其反向。

状态转移: 对于当前血量 \(x\),我们有三种情况:用一号大炮单独打一次,用二号大炮单独打一次,二者一起打一次(中间可能包扩各自打)。对于前两种情况,比较简单:

\(dp[x] = min(dp[x - (p1 - p)] + t1, dp[x - (p2 - p)] + t2\)

对于第三种情况,画图考虑:

对于 \(t_2\) 大于 \(t_1\) 的情况,如此考虑:两门炮先各自打若干炮,然后最后一起打一炮。这样就可以覆盖所有的情况了。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long

template <class T>
inline void read(T& a){
	T x = 0, s = 1;
	char c = getchar();
	while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
	a = x * s;
	return ;
}

ll dp[N]; 
ll p1, t1;
ll p2, t2; 
ll M, p; 

int main(){
  // freopen("hh.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);  
  read(p1), read(t1);
  read(p2), read(t2);
  read(M), read(p);

  memset(dp, 0x3f3f3f3f3f3f3f, sizeof(dp)); 
  dp[0] = 0; 

  for(int i = 1; i <= M; i++){
    dp[i] = min(dp[i], dp[max(0ll, i - p1 + p)] + t1); 
    dp[i] = min(dp[i], dp[max(0ll, i - p2 + p)] + t2); 
    for(int j = 1; j <= i; j++){
      if(j * t1 >= t2){
        ll tmp = (j - 1) * (p1 - p) + ((j * t1 - t2) / t2) * (p2 - p) + (p1 + p2 - p); 
        dp[i] = min(dp[i], dp[max(0ll, (ll)i-tmp)] + j * t1); 
      }
      if(j * t2 >= t1){
        ll tmp = (j - 1) * (p2 - p) + ((j * t2 - t1) / t1) * (p1 - p) + (p1 + p2 - p); 
        dp[i] = min(dp[i], dp[max(0ll, (ll)i-tmp)] + j * t2); 
      }
    }
  }

  cout << dp[M] << endl; 
  return 0;
}

标签:Educational,Rated,int,题解,ll,read,while,dp,getchar
From: https://www.cnblogs.com/wondering-world/p/16803622.html

相关文章

  • Educational Codeforces Round 137 (Rated for Div. 2)
    A.Password计算出现的数,从这些数中任意选两不同的,每种组合6种方案,计算输出即可#include<bits/stdc++.h>usingnamespacestd;intmain(){intt;cin>>t;......
  • Packet Tracer更改字体后命令行黑屏问题解决
    黑屏现象问题描述做PacketTracer实验时,突然感觉字体有点小,就去调整了一下字体,但是,改完发现命令行和鼠标悬停信息都变成了黑屏PacketTrac上网查阅之后只找......
  • 【题解】CF1151C Problem for Nazar(二分答案)
    【题解】CF1151CProblemforNazar距离CSP剩下10天了,据说考前写题解可以增加RP所以我来写一篇题解+水点贡献分看题解区没有用二分答案来解决这道题的,我来提供一个......
  • CF641E 题解
    前言题目传送门!更好的阅读体验?非常套路的cdq分治。思路把所有操作统一存下来。将\(x\)离散化。\(i\)能被\(j\)统计,前提是\(a_i\)的操作时间早于\(a_j\)。......
  • 蓝桥杯第二次模拟赛JAVA题解
    目录​​第一题......
  • Codeforces Round #827 (Div. 4) 复盘+题解
    原比赛链接复盘:ABC签到,手速太慢了。D捣鼓了好久才想起来从更小的值域出发去做。E简单二分答案。然后就timeout了。D题搞错方向浪费太久时间了。F思维题,拐两个弯再$r......
  • P7868 VUDU 题解
    P7868VUDU题解提供一种不需要使用离散化,从\(0/1\)分数规划的角度推导的思路。然而考试的时候没想到求逆序对挂掉了分析题意很清楚了,就是求给出的序列中,对于一段任意长......
  • CF309E 题解
    11:30,过题。12:50,忘记做法。吃饭时不该看未来日记的,Ynoj害人不浅(确信)。以上为个人吐槽。题目大意不知道题目翻译是个啥。。。但讨论区有大佬给出了精确的翻译。我改得......
  • Educational Codeforces Round 112 D
    D.SayNotoPalindromes很牛逼我们手动模拟一下可以知道只有3个字母不构成回文串只有可能是这样的abcabc....acbacb.......6种情况所以直接暴力预处理即可#inclu......
  • AcCoders 10692:【2022NOIP联测10 10月17日】交换(swap) 题解
    考虑把一次交换产生的贡献记录在交换的两个数字中较小的那个数字上。则构造一个好的序列的过程可以看成是:按照从小到大的顺序枚举每个数,每次选择将这个数放在序列的左边或......