Zerojudge第二屆簡單的小競賽題解

第二次舉辦簡單的小競賽,感覺有點難,但對某些人來說應該算很簡單的,有 $4$ 題流程題和 $12$ 題競賽題,競賽題有下半場和上半場。

A:簽到 (Zerojudge_f026不公開)

題目:輸出 $\text{Checked!!!}$

解法:直接輸出。

#pragma GCC optimize("O3")
#include <iostream>
using namespace std;
int main() {
    cout << "Checked!!!\n";
}

B:規則說明 (Zerojudge_f027不公開)

題目:輸入帳密,輸出帳密。

解法:輸出帳密。

#pragma GCC optimize("O3")
#include <iostream>
using namespace std;
int main() {
    char ac[21], ps[21];
    scanf ("Account:%s\n", ac);
    scanf ("Password:%s", ps);
    printf ("%s\n%s\nLog in\n", ac, ps);
}

1-1:Say HELLO! (Zerojudge_e412練習題)

題目:輸入姓名,輸出姓名。

解法:輸出姓名,輸入記得要讀取整行。

#pragma GCC optimize("O3")
#include <iostream>
using namespace std;
int main() {
    string str;
    while (getline (cin, str))
        cout << "HELLO," << str << '\n';
}

1-2:行不行 (Zerojudge_f028練習題)

題目:輸入姓名、分數,問行不行。

解法:輸出姓名,若分數 $≥60$,輸出 $\text{Yes}$,否則輸出 $\text{No}$。

#pragma GCC optimize("O3")
#include <iostream>
using namespace std;
int main() {
    string str;
    int n;
    while (cin >> str >> n)
        cout << str << ':' << (n >= 60 ? "Yes\n" : "No\n");
}

1-3:OREOREO! (Zerojudge_e698)

題目:輸入餅乾、餅乾餡、餅乾寬、高,輸出餅乾。

解法:讀取字串,輸出餅乾。

#pragma GCC optimize("O3")
#include <iostream>
using namespace std;
int on, oh, ren, reh;
char o, re;
void fo() {
    if (on >= ren)
        for (int i = 0; i < oh; i++)
            cout << string (on, o) << '\n';
    else
        for (int i = 0; i < oh; i++)
            cout << string ( (ren - on) / 2, ' ') << string (on, o) << '\n';
}
void reo() {
    if (on <= ren)
        for (int i = 0; i < reh; i++)
            cout << string (ren, re) << '\n';
    else
        for (int i = 0; i < reh; i++)
            cout << string ( (on - ren) / 2, ' ') << string (ren, re) << '\n';
}
int main() {
    while (cin >> on >> oh >> ren >> reh) {
        cin >> o >> re;
        int t;
        cin >> t;
        while (t--) {
            string str;
            cin >> str;
            for (int i = 0; i < str.length(); i++) {
                if (str[i] == 'O')
                    fo();
                else
                    i++, reo();
            }
            cout << '\n';
        }
    }
}

1-4:奇怪的隕石(Zerojudge_e990)

題目:給你隕石半衰期 $T$,問過多久變 $n$ 倍。

解法:可得公式 $-T\times log_2(n)$。

#pragma GCC optimize("O3")
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main() {
    double T, n;
    while (cin >> T >> n)
        cout << fixed << setprecision (3) << -T*log2 (n) << '\n';
}

1-5:S形的矩陣 (Zerojudge_f034練習題)

題目:給你 $n$,輸出 $n\times n$ 的 $S$ 形的矩陣。

解法:輸出。

#pragma GCC optimize("O3")
#include <stdio.h>
int main() {
    int n;
    while (~scanf ("%d", &n)) {
        for (int i = 0; i < n; i++) {
            if (i % 2 == 0)
                for (int j = 0; j < n; j++)
                    printf ("%d ", i * n + j + 1);
            else
                for (int j = n - 1; j >= 0; j--)
                    printf ("%d ", i * n + j + 1);
            printf ("\n");
        }
        printf ("\n");
    }
}

1-6:Caidocraft的構造改革!(Zerojudge_f010)

題目:給你一些指令,有些要輸出,詳情請見上方連結。

解法:測資不是很大,直接循序搜索就好了,$\text{Code}$ 有點亂。

#pragma GCC optimize("O3")
#include <iostream>
#include <map>
#include <vector>
#include <sstream>
#define f first
#define s second
#define x first
#define y second
using namespace std;
int hp, sat, walk, run;
pair<int, int>At, re;
map<string, int>food;
map<string, int>monster;
vector<pair<string, int> >backpack;
map<pair<int, int>, vector<pair<string, int> > >fall;
void init() {
    hp = sat = 10, At.x = At.y = re.x = re.y = walk = run = 0;
}
int find_string (vector<pair<string, int> >vec, string str) {
    for (int i = 0; i < vec.size(); i++)
        if (vec[i].f == str)
            return i;
    return -1;
}
void die() {
    for (int i = 0; i < backpack.size(); i++) {
        int fi = find_string (fall[At], backpack[i].f);
        if (fi == -1)
            fall[At].push_back (backpack[i]);
        else
            fall[At][fi].s += backpack[i].s;
    }
    At = re, hp = sat = 10;
    backpack.clear();
}
void suck() {
    if (fall.count (At)) {
        for (int i = 0; i < fall[At].size(); i++) {
            int fi = find_string (backpack, fall[At][i].f);
            if (fi == -1)
                backpack.push_back (fall[At][i]);
            else
                backpack[fi].s += fall[At][i].s;
        }
        fall.erase (fall.find (At));
    }
}
void sleep() {
    re = At;
}
void create_monster (string str, int n) {
    monster[str] = n;
}
void attacked (string str) {
    hp -= monster[str];
    if (hp <= 0)
        die();
}
void pick (string str, int n) {
    int fi = find_string (backpack, str);
    if (fi == -1)
        backpack.push_back ({str, n});
    else
        backpack[fi].s += n;
}
void turn() {
    if (sat <= 10)
        return;
    int more = sat - 10;
    sat = 10;
    more /= 2;
    hp += more;
    if (hp > 10)
        hp = 10;
}
void eat (string str, int n) {
    int fi = find_string (backpack, str);
    backpack[fi].s -= n;
    if (backpack[fi].s == 0)
        backpack.erase (backpack.begin() + fi);
    sat += food[str] * n;
    turn();
}
void Walk (string to, int n) {
    int de;
    walk += n, de = walk / 50, walk %= 50;
    sat -= de;
    if (sat <= 0)
        die();
    else {
        if (to == "East")
            At.x += n;
        else if (to == "West")
            At.x -= n;
        else if (to == "North")
            At.y += n;
        else if (to == "South")
            At.y -= n;
        suck();
    }
}
void Run (string to, int n) {
    int de;
    run += n, de = run / 25, run %= 25;
    sat -= de;
    if (sat <= 0)
        die();
    else {
        if (to == "East")
            At.x += n;
        else if (to == "West")
            At.x -= n;
        else if (to == "North")
            At.y += n;
        else if (to == "South")
            At.y -= n;
        suck();
    }
}
void think (string strr) {
    stringstream ss;
    ss << strr;
    string str;
    ss >> str;
    if (str == "Walk") {
        string to;
        int n;
        ss >> to >> n;
        Walk (to, n);
        return;
    }
    if (str == "Run") {
        string to;
        int n;
        ss >> to >> n;
        Run (to, n);
        return;
    }
    if (str == "Sleep") {
        sleep();
        return;
    }
    if (str == "Create") {
        string name;
        int n;
        ss >> name >> n;
        create_monster (name, n);
        return;
    }
    if (str == "Attacked") {
        string name;
        ss >> name >> name;
        attacked (name);
        return;
    }
    if (str == "Pick") {
        string thing, test;
        int n;
        ss >> thing >> n;
        ss >> test;
        if (! (test[0] >= '0' && test[0] <= '9')) {
            int fi = find_string (backpack, thing);
            if (fi == -1)
                backpack.push_back ({thing, n});
            else
                backpack[fi].s += n;
        } else {
            backpack.push_back ({thing, n});
            int mo = 0;
            for (int i = 0; i < test.length(); i++)
                mo = mo * 10 + test[i] - '0';
            food[thing] = mo;
        }
        return;
    }
    if (str == "Eat") {
        string fo;
        int n;
        ss >> fo >> n;
        eat (fo, n);
        return;
    }
    if (str == "Print") {
        string dd;
        ss >> dd;
        if (dd == "HP")
            cout << "HP:" << hp << '\n';
        else if (dd == "SAT")
            cout << "SAT:" << sat << '\n';
        else if (dd == "At")
            cout << "At:(" << At.x << ',' << At.y << ")\n";
        else {
            cout << "Backpack:\n";
            for (int i = 0; i < backpack.size(); i++)
                cout << backpack[i].f << ' ' << backpack[i].s << '\n';
        }
    }
}
int main() {
    init();
    string str;
    while (getline (cin, str)) {
        think (str);
    }
}

C:中場休息 (Zerojudge_f029不公開)

題目:輸出最後吃多飽。

解法:一直加直到 $\text{EOF}$。

#pragma GCC optimize("O3")
#include <iostream>
using namespace std;
int main() {
    int sum = 0, n;
    while (cin >> n)
        sum += n;
    cout << sum << '\n';
}

2-1:測量速度 (Zerojudge_f030練習題)

題目:輸入姓名,$n$ 秒 $k$ 個字,輸出多快。

解法:輸出 $k/n$。

#pragma GCC optimize("O3")
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
    string str;
    double s, k;
    while (cin >> str >> s >> k)
        cout << str << ':' << fixed << setprecision (3) << k / s << '\n';
}

2-2:0、1 (Zerojudge_f031練習題)

題目:輸入 $0、1$,輸出 $\text{White、Black}$。

解法:判斷是 $0$ 還是 $1$。

#pragma GCC optimize("O3")
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
    bool b;
    while (cin >> b)
        cout << (b == 0 ? "White\n" : "Black\n");
}

2-3:巴尾萊鳥 (Zerojudge_f011)

題目:輸入 $n$ 次方程式、切點,求切線與 $X$ 軸交點。

解法: 斜率 $=dy/dx$,對 $n$ 次方程式微分可求得斜率,切線:$y-b=m(x-a)$,將 $(s,0)$ 代 入,$0-b=m(s-a)$,$s=-b/m+a$。 但若 $m=0$,會與 $X$ 軸平行,此時判斷 $b$ 是否等於 $0$。

#pragma GCC optimize("O3")
#include <iostream>
#include <iomanip>
using namespace std;
double dpow (double n, int p) {
    if (p == 0)
        return 1;
    double re = 1;
    for (int i = 1; i <= p; i++)
        re *= n;
    return re;
}
int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        double a, b = 0, m = 0;
        cin >> n;
        int c[n + 1];
        for (int i = 0; i <= n; i++)
            cin >> c[i];
        cin >> a;
        for (int i = 0; i <= n; i++)
            b += dpow (a, n - i) * c[i];
        for (int i = 0; i < n; i++)
            m += dpow (a, n - i - 1) * c[i] * (n - i);
        if (m == 0 && b == 0)
            cout << "It can sleep everywhere!\n";
        else if (m == 0)
            cout << "It cannot sleep!\n";
        else
            cout << '(' << fixed << setprecision (3) << -b / m + a << ",0)\n";
    }
}

2-4:奶油機器人 (Zerojudge_f012)

題目:機器人在白色平面由 $(0,0)$ 出發,所在的格子為白色時,使得格子變成黑色,並向右轉 $90$ 度,前進一格;所在的格子為黑色時,使得格子變成白色,並向左轉 $90$ 度,前進一格。

解法:由維基百科可知,在 $10000$ 多格後會 $104$ 個一循環,所以 $n$ 取 $15000$,只需存前 $15000$ 格,和循環的 $104$ 格,若大於 $15000$ 時,加上去即可。

#pragma GCC optimize("O3")
#include <iostream>
#include <map>
#define x first
#define y second
using namespace std;
int dic = 0;
map<pair<int, int>, bool>color;
pair<int, int>ans[15001], at, cir[105];
void turn_go (bool bo) {
    if (bo == 1)
        dic = (dic + 1) % 4;
    else if (dic == 0)
        dic = 3;
    else
        dic--;
    if (dic == 0)
        at.y++;
    else if (dic == 1)
        at.x++;
    else if (dic == 2)
        at.y--;
    else if (dic == 3)
        at.x--;
}
void init() {
    for (int i = 1; i <= 15000; i++) {
        if (color[at] == 0) {
            color[at] = 1;
            turn_go (1);
            ans[i] = at;
        } else {
            color[at] = 0;
            turn_go (0);
            ans[i] = at;
        }
    }
    for (int i = 1; i <= 104; i++) {
        if (color[at] == 0) {
            color[at] = 1;
            turn_go (1);
            cir[i] = at;
        } else {
            color[at] = 0;
            turn_go (0);
            cir[i] = at;
        }
    }
}
int main() {
    init();
    long long n;
    while (cin >> n) {
        if (n <= 15000)
            cout << '(' << ans[n].x << ',' << ans[n].y << ")\n";
        else {
            n -= 15000;
            long long mod = n % 104, div = n / 104;
            if (mod == 0)
                div--, mod = 104;
            cout << '(' << (long long) cir[mod].x - 2 * div << ',' << (long long) cir[mod].y - 2 * div << ")\n";
        }
    }
}

2-5:費の數列 (Zerojudge_f032練習題)

題目:求費氏數列第 $n$ 項 $(n≤10000)$。

解法:一開始先存好,輸入時直接輸出就好了。

#pragma GCC optimize("O3")
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
    int f[10001], k;
    f[1] = f[2] = 1;
    for (int i = 3; i <= 10000; i++)
        f[i] = (f[i - 1] + f[i - 2]) % 10007;
    while (cin >> k)
        cout << f[k] << '\n';
}

2-6:N項的費氏數列 (Zerojudge_f013)

題目:求 $n$ 項費氏數列的第 $k$ 項 $(k<=2^{50})$

解法:都沒人解出這題,要不然就是直接算 $33\%$,或矩陣快速冪 $67\%$,其實是要先判斷哪一種做法比較快,因為矩陣快速冪在乘的時間會用到 $n^3$,$k$ 小時就很耗時間。
我有想過用 $queue$,但都差不多快。

#pragma GCC optimize("O3")
#include <iostream>
#define mod 1000000007
#define ll long long
using namespace std;
int t, n, ans[30][30], mult[30][30];
ll k;
void init() {
    for (int i = 0; i < n; i++)
        mult[0][i] = ans[0][i] = 1;
    for (int i = 1; i < n; i++)
        for (int j = 0; j < n; j++)
            mult[i][j] = ans[i][j] = (i - 1 == j ? 1 : 0);
}
bool faster() {
    ll zero = (k - n) * n, one, bit = 0, m = k - n - 1;
    while (m)
        bit += ( (m & 1) ? 2 : 1), m >>= 1;
    one = n * n * n * bit;
    if (zero <= one)
        return 0;
    return 1;
}
void solve0() {
    int dp[n];
    ll now = n;
    for (int i = 0; i < n; i++)
        dp[i] = 1;
    for (ll i = n; i < k; i++) {
        ll sum = (2 * now - dp[0]) % mod;
        if (sum < 0)
            sum += mod;
        for (int j = 0; j < n - 1; j++)
            dp[j] = dp[j + 1];
        dp[n - 1] = now;
        now = sum;
    }
    cout << dp[n - 1] << '\n';
}
void mult_mult() {
    int arr[n][n];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            arr[i][j] = mult[i][j];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++) {
            mult[i][j] = 0;
            for (int k = 0; k < n; k++)
                mult[i][j] = ( (ll) arr[i][k] * arr[k][j] + mult[i][j]) % mod;
        }
}
void ans_mult() {
    int arr[n][n];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            arr[i][j] = ans[i][j];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++) {
            ans[i][j] = 0;
            for (int k = 0; k < n; k++)
                ans[i][j] = ( (ll) mult[i][k] * arr[k][j] + ans[i][j]) % mod;
        }
}
void solve1() {
    ll m = k - n - 1, sum = 0;
    while (m) {
        if (m & 1)
            ans_mult();
        mult_mult();
        m >>= 1;
    }
    for (int i = 0; i < n; i++)
        sum = (sum + ans[0][i]) % mod;
    cout << sum << '\n';
}
void solve() {
    cin >> n >> k;
    if (k <= n) {
        cout << "1\n";
        return;
    }
    init();
    if (faster() == 0)
        solve0();
    else
        solve1();
}
int main() {
    cin >> t;
    while (t--)
        solve();
}

D:離場 (Zerojudge_f033不公開)

題目:給你一些物品,判斷有多少個。

解法:累加到 $\text{EOF}$。

#pragma GCC optimize("O3")
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
    string str;
    int n = 0;
    while (cin >> str)
        n++;
    cout << n << '\n';
}


我的分享就到這裡結束了,如果喜歡我的 $\text{Blog},歡迎追蹤!

留言

熱門文章