Codeforces Goodbye 2018 上分记

2018最后一场cf了,how time fies!

作为一个中学生,有时间能参加的cf比赛实在是少之又少,以至于我现在才打了3场现场比赛,其他的都是virtual participation。

终于把C题做出来辣!终于涨rating辣!

下面把我会的题目都打上来:

A题

woc这是英语阅读题啊!

题面那么长,说到底就是求一个最大的\(n+(n+1)+(n+2)\)和。

显然分三种情况,一一枚举即可。

代码:

#include<iostream>

int main()
{
    int y, b, r; std::cin >> y >> b >> r;
    if(y + 1 <= b && y + 2 <= r)
    {
        std::cout << y + y + 1 + y + 2 << std::endl;
    }
    else if(b - 1 <= y && b + 1 <= r)
    {
        std::cout << 3 * b << std::endl;
    }
    else if(r - 2 <= y && r - 1 <= b)
    {
        std::cout << r + r - 1 + r - 2 << std::endl;
    }
    return 0;
}

B题

同样是一道英语阅读题啊!

大意就是:给你\(n\)个点,然后有\(n\)个提示,提示与上面给的点一一对应,但不知道具体对应关系,求目标点坐标。

我差点不会做

看到\(n\)只有\(1000\),大胆使用暴力算法:把所有可能指示的坐标都弄出来,最终重合了\(n\)次的那个点就是目标点了。

但是坐标范围是\([-3 \times 10^6,3 \times 10^6]\),没办法开这样的数组啊!

仔细想一想,只需要hash一下就完事了。开龙龙显然存得下。

最后用最暴力的std::map过掉system test。

代码:

#include<iostream>
#include<map>
using namespace std;
#define ll long long
const int maxn = 1005;
struct Nodes
{
    int x, y;
} s[maxn];
int n;
map<ll,int> mmp;
ll id(int x, int y)
{
    return (x - 3000000) * 3000000 + y - 3000000;
}
int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> s[i].x >> s[i].y;
    }
    for(int i = 1; i <= n; i++)
    {
        int xx, yy; cin >> xx >> yy;
        for(int j = 1; j <= n; j++)
        {
            int newx = s[j].x + xx, newy = s[j].y + yy;
            //std::cout << newx << ' ' << newy << endl;
            mmp[id(newx, newy)]++;
            if(mmp[id(newx, newy)] == n)
            {
                std::cout << newx << ' ' << newy << endl;
                return 0;
            }
        }
    }
    return 0;
}

C题

终于不是阅读题了。但是题目就变难了。

看到\(n \leq 10^9\),就知道要凉辣 不是轻轻松松就想出来的。

想不出来打暴力看规律,这道题暴力能解决的\(n\)还能到几十万。

暴力看规律(看了好久的规律)可以发现一些最基本的性质:

  • \(n\)是质数时,答案只有1和\(n\)的某个倍数。
  • \(k\)的前半部分与后半部分是对称的。
  • 当长度相同时,对应的答案也相同。并且,长度相同中,\(k\)最小的那个方案,所有的数都是递增的。

接下来通过上个厕所等奇技淫巧可以发现解题的关键结论:**方案的长度与\(k\)有关,关系是\(gcd(n,k) \times len = n\) **

所以我们通过枚举\(n\)的所有因数,可以得到所有的最小\(k\),然后可以发现要求的和就是等比数列呀!所以开个龙龙套个公式就可以求出和。

我们这样的枚举是不会有重复的,所以复杂度是优美的\(O(\sqrt{n})\)

代码:

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

#define ll long long
vector<ll> vec;
ll n;

ll getsum(ll a1, ll d, ll n)
{
    return n * a1 + n * (n - 1) / 2 * d;
}
int main()
{
    cin >> n;
    for(ll i = 1; i * i <= n; i++)
    {
        if(n % i == 0)
        {
            ll temp = n / i;
            // solve i
            //cout << getsum(1, temp, i) << endl;
            vec.push_back(getsum(1, temp, i));
            if(i != temp)
            {
                // solve temp
                //cout << getsum(1, i, temp) << endl;
                vec.push_back(getsum(1, i, temp));
            }
        }
    }
    sort(vec.begin(), vec.end());
    for(auto it = vec.begin(); it != vec.end(); ++it)
    {
        cout << *it << ' ';
    }
    cout << endl;
    return 0;
}

D题

其实我不会,看到dp我就溜了。那个时候好像已经12点了。

但是我要留坑!

希望我不会咕咕

事后

怀着涨rating的希望醒来,发现自己真的涨rating辣!

涨到1424,离超越最开始的1484还差一场比赛!回归青名!(虽然青名也不厉害)

无事的事后看到tourist,又涨rating了?!3559!破天荒的高!

tourist一分钟内切掉了A题!

最近的一场Hello 2019是没办法打了。我不知道还能不能碰到一场div.3来上分了。

不管了,反正ADD OIL就完事辣!

posted @ 2018-12-31 18:11  Garen-Wang  阅读(1214)  评论(0编辑  收藏  举报