Codeforces Round #621 (Div. 1 + Div. 2)

A. Cow and Haybales

题目大意: 给你n个数,你可以使得将相邻的数转移1,即一个加1,一个减1,你可以转移d次,问a1最大是多少。

核心思路贪心+模拟:从第 i 个位置转移到 1 的位置需要( i - 1 ) 步,优先从离 1 位置近的转移。

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
int main()
{
    ios::sync_with_stdio(false);
    int t;
    while (cin >> t)
    {
        while (t--)
        {
            int n, d;
            cin >> n >> d;
            int a[105];
            for (int i = 1; i <= n; i++)
                cin >> a[i];
            int cnt = 0;
            for (int i = 2; i <= n; i++)
            {
                if (a[i])
                {
                    if ((i - 1) * a[i] > d) //用完d
                    {
                        a[1] += (d / (i - 1));
                        break;
                    }
                    else //用不完d
                    {
                        a[1] += (a[i]);
                        d -= ((i - 1) * a[i]);
                    }
                }
            }
            cout << a[1] << endl;
        }
    }
    return 0;
}

B. Cow and Friend

题目大意让你从(0,0)−>(x,0),并且走的点的距离等于某个 ai 。问最小的步数。

方法一:

核心思路: 对 ai 进行从小到大排列,寻找大于等于x的 ai ,如果找到,则 ai=x 则就需要1步;如果 ai > x则需要 2 步;

如果找不到,则一次走的最大的值为 ai ,步数为 [ ai / x ] 向上取整。

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1e5 + 5;
int a[maxn];
int main()
{
    ios::sync_with_stdio(false);
    int t;
    while (cin >> t)
    {
        while (t--)
        {
            int n, x, ans;
            cin >> n >> x;
            memset(a, 0, sizeof(a));
            for (int i = 1; i <= n; i++)
                cin >> a[i];
            sort(a + 1, a + 1 + n);
            int t = upper_bound(a + 1, a + 1 + n, x) - a; //比x大
            if (t == 1 + n)                               //都比x小
            {
                if (x % a[n] == 0)
                    ans = x / a[n];
                else
                    ans = x / a[n] + 1;
            }
            else //>x的
            {
                if (t > 1)
                {
                    if (a[t - 1] < x)
                        ans = 2;
                    else
                        ans = 1;
                }
                else
                    ans = 2;
            }
            cout << ans << endl;
        }
    }
    return 0;
}

方法二:

官方题解:

核心思路: 跟上面的思路是一样的,如果不能找到一步就走完的,就找到最大的向上取整。

官方AC代码:

#include <iostream>
#include <set>
#include <algorithm>
using namespace std;

set<int>a;
//you don't have to use set, it was just easier for us

int main(){
  int T; cin>>T;
  while (T--){
    int N,X;
    cin>>N>>X;
    int far=0; //largest favorite number
    for (int i=0;i<N;i++){
      int A;
      cin>>A;
      a.insert(A);
      far=max(far,A);
    }
    if (a.count(X)) //X is favorite number
      cout<<1<<endl;
    else
      cout<<max(2,(X+far-1)/far)<<endl; //expression as explained in tutorial,向上取整的操作
    a.clear();
  }
}

C. Cow and Message

题目大意 给你一个字符串都是小写字母,然后让你找它的子序列,使得子序列中的字符程等差序列。并输出它的出现次数。

核心思路 DP

  1. 分析长度为 1 的子串,它就是自己本身出现的次数。

  2. 分析长度为 2 的子串,它就是状态转移方程为:表示 ( i , j) 位置出现的次数。
    d p [ i ] [ j ] + = c n t [ i ] dp[i][j]+=cnt[i]

  3. 分析长度为 3 的子串,3的字串必定是有2的字串,他出现的次数定小于2子串出现的次数。

  4. 综上我们就分析长度为 1 和 2 的字串出现的次数即可。

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
ll cnt[26], dp[26][26];
ll ans;
int main()
{
    ios::sync_with_stdio(false);
    string s;
    cin >> s;
    int len = s.size();
    for (int i = 0; i < len; i++)
    {
        int c = s[i] - 'a';
        for (int j = 0; j < 26; j++)
            dp[j][c] += cnt[j];
        cnt[c]++;
        ans = max(ans, cnt[c]);
    }
    for (int i = 0; i < 26; i++)
        for (int j = 0; j < 26; j++)
            ans = max(ans, dp[i][j]);
    cout << ans << endl;
    return 0;
}
发布了34 篇原创文章 · 获赞 35 · 访问量 6517

猜你喜欢

转载自blog.csdn.net/acm_durante/article/details/104379393