1. 程式人生 > >Codeforces Goodbye 2018 上分記

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就完事辣!