Educational Codeforces Round 32[题解]

来源:互联网 发布:statnba数据 编辑:程序博客网 时间:2024/06/04 23:35

比赛时只过了5道题,ABCDE。先写下题解,剩下的FG等补完题再更。

A:

题意:

给定一个数列, 求极值点的个数。极值点定义为比相邻的两个数都大,或者都小的点。

题解

直接一遍扫过去判断即可。注意端点只有一个相邻的数,遍历范围为2 到 n - 1。判断条件为a[i] > a[i - 1] && a[i] > a[i + 1] || a[i] < a[i - 1] && a[i] < a[ i + 1]。

#include <bits/stdc++.h>using namespace std;const int maxn = 1010;int a[maxn];int main(){  int n;  while(~scanf("%d", &n))  {    for(int i = 1; i <= n; i++)      scanf("%d", &a[i]);    int ans = 0;    if(n <= 2)  ans = 0;    else    {      for(int i = 2; i <= n - 1; i++)        if(a[i] > a[i - 1] && a[i] > a[i + 1] || a[i] < a[i - 1] && a[i] < a[ i + 1])          ans++;    }    printf("%d\n", ans);  }}

B:

题意:

给定一个机器人的每一步的运动方向,问你机器人最多按这个走多少步能保证回到起点。

题解:

分析易知,若向上(U)走一步,则之后必须需要向下(D)走一步才能回到原点,左右同理。
因此最多上下的次数为U的次数和D的次数中的最小值*2。
于是答案就是U的次数和D的次数中最小值加上L和R中的最小值。再乘以2就是。

#include <bits/stdc++.h>using namespace std;int get(char c){  if(c == 'U')  return 1;  else  if(c == 'D')  return 2;  else  if(c == 'L')  return 3;  else  return 4;}char buf[1010];int cnt[5];int main(){  int n;  while(~scanf("%d", &n))  {    scanf(" %s", buf);    memset(cnt, 0, sizeof cnt);    for(int i = 0; buf[i]; i++)    cnt[get(buf[i])]++;    int ans = 0;    ans = 2 * min(cnt[1], cnt[2]) + 2 * min(cnt[3], cnt[4]);    printf("%d\n", ans);  }}

C:

题意:

给定一个字符串,求最大的k,使得存在一个字符c是该串的k-dominant character. k-dominant character定义为字符串的任意长度为k的子串中均包含有字符c。

题解:

对于一个给定的字符c,考虑其可以构成的k值的最小值。任意长度为k的子串都包含有c,也就是串中c的间隔以及c与端点的最大距离为k。因此最小值即为所有c间隔中的最大值。再对于所有字符的最小k值取个最小值,即为答案。

#include <bits/stdc++.h>using namespace std;const int maxn = 100010;int pos[28];int Mx[28];char buf[maxn];int main(){  while(~scanf(" %s", buf))  {    memset(pos, -1, sizeof pos);    memset(Mx, 0, sizeof Mx);    int len = strlen(buf);    for(int i = 0; buf[i]; i++){      int t = buf[i] - 'a' + 1;      Mx[t] = max(Mx[t], i - pos[t]);      pos[t] = i;    }    for(int i = 1; i <= 26; i++)    {      Mx[i] = max(Mx[i], len - pos[i]);      pos[i] = len;    }    int ans = maxn;    for(int i = 1; i <= 26; i++)      if(Mx[i])        ans = min(ans, Mx[i]);    printf("%d\n", ans);  }}

D:

题意:

给定n,k,问对于一个n的全排列,最多错排k个元素的排列数。

题解:

由错排公式有D0 = 1,D1 = 0, D2 = 1, D3 = 2, D4 = 9;
因此恰好错排k个的数目为C(n,k) * Dk;
所求排列数为ki=1C(n,i)Di
数据范围比较小,直接算即可。

#include <bits/stdc++.h>using namespace std;#define ll long longll C(ll n, ll k){  ll res = 1;  for(ll i = 1, j = n; i <= k; i++, j--)    res = res * j / i;  return res;}int main(){  ll n, k;  while(~scanf("%lld%lld", &n, &k))  {    ll ans = 0;    switch(k)    {      case 4: ans += C(n, 4) * 9;      case 3: ans += C(n, 3) * 2;      case 2: ans += C(n, 2);      case 1: ans++;    }    printf("%lld\n", ans);  }}

E:

题意:

给出n和m,一个n个数a[i],求从中任意选出一些数,使得 a[i]%m 的最大值。

题解:

先对a[i] 取模,然后问题就类似于一个超大容量背包问题,直接dp显然不可行。我们可以采取常用的对半枚举,然后二分查找的方法求解。
枚举对前n / 2个元素能够构成的所有情况,加入到set ssr1中,再枚举剩余的元素,加入到set ssr2中,然后枚举一个集合的元素x,查找另一个集合中 <= m - 1 - x 的最大元素。

#include <bits/stdc++.h>using namespace std;#define ll long longset<ll> ssr1, ssr2, sr;set<ll>::iterator ite, ite2;ll a[110];int main(){  int n;  ll m;  while(~scanf("%d%lld", &n, &m))  {    if(n == 1)    {      ll t;      scanf("%lld", &t);      printf("%lld\n", t % m);    }    else    {      for(int i = 1; i <= n; i++)      {        scanf("%lld", &a[i]);        a[i] %= m;      }      ssr1.clear();      ssr1.insert(0);      for(int i = 1; i <= n / 2; i++)      {        sr.clear();        for(ite = ssr1.begin(); ite != ssr1.end(); ite++)          sr.insert((*ite + a[i]) % m);        for(ite = sr.begin(); ite != sr.end(); ite++)          ssr1.insert(*ite % m);      }      ssr2.clear();      ssr2.insert(0);      for(int i = n / 2 + 1; i <= n; i++)      {        sr.clear();        for(ite = ssr2.begin(); ite != ssr2.end(); ite++)          sr.insert((*ite + a[i]) % m);        for(ite = sr.begin(); ite != sr.end(); ite++)          ssr2.insert(*ite % m);      }      ll ans = 0;      for(ite = ssr1.begin(); ite != ssr1.end(); ite++)      {        ll t = *ite;        ite2 = ssr2.lower_bound(m - t);        while(ite2 == ssr2.end() || *ite2 > m - 1 - *ite) ite2--;          ans = max(ans, (*ite + *ite2) % m);      }      printf("%lld\n", ans);    }  }}