2024牛客寒假算法基础集训营1

A

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 998244353;
const int N = 1e6 + 10, M = 25;

void solve()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    int cnt = 0;
    for (auto i : s)
    {
        if (i == 'D' && cnt == 0)
            cnt++;
        if (i == 'F' && cnt == 1)
            cnt++;
        if (i == 'S' && cnt == 2)
            cnt++;
    }
    cout << (cnt == 3 ? 1 : 0) << " ";
    cnt = 0;
    for (auto i : s)
    {
        if (i == 'd' && cnt == 0)
            cnt++;
        if (i == 'f' && cnt == 1)
            cnt++;
        if (i == 's' && cnt == 2)
            cnt++;
    }
    cout << (cnt == 3 ? 1 : 0) << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    cin >> _;
    while (_--)
        solve();
    return 0;
}

B

注意特判一下用\((1,-1),(1,1),(2,0)\)围起来的特殊情况

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 998244353;
const int N = 1e6 + 10, M = 25;
int dx[] = {-1, -1, -1, 1, 1, 1}, dy[] = {-1, 0, 1, -1, 0, 1};
map<pii, bool> mp;
void solve()
{
    ll n;
    cin >> n;
    mp.clear();
    vector<pii> p(n);
    for (auto &[x, y] : p)
    {
        cin >> x >> y;
        mp[{x, y}] = 1;
    }
    sort(p.begin(), p.end(), [&](pll a, pll b)
         { 
            if(a.y!=b.y)
         return a.y < b.y;
         return a.x<b.x; });
    int ans = 3, ansr = 2, ansl = 2;
    for (auto [x, y] : p)
    {
        if (y < 0)
        {
            for (int j = 0; j < 6; j++)
            {
                int xx = x + dx[j], yy = y + dy[j];
                if (xx <= 2 && xx >= 1 && yy <= 1e9 && yy >= -1e9)
                {
                    if (mp[{xx, yy}])
                        ansl = 0;
                }
            }
            ansl = min(ansl, 1);
        }
        else if (y > 0)
        {
            for (int j = 0; j < 6; j++)
            {
                int xx = x + dx[j], yy = y + dy[j];
                if (xx <= 2 && xx >= 1 && yy <= 1e9 && yy >= -1e9)
                {
                    if (mp[{xx, yy}])
                        ansr = 0;
                }
            }
            ansr = min(ansr, 1);
        }
        else
        {
            ansl = min(ansl, 1);
            ansr = min(ansr, 1);
        }
    }
    if (mp[{2, 0}])
        ans--;
    if (mp[{1, -1}])
        ans--;
    if (mp[{1, 1}])
        ans--;
    cout << min(ans, ansl + ansr) << endl;
    // cout << ansl + ansr << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    cin >> _;
    while (_--)
        solve();
    return 0;
}

C

二分答案

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 998244353;
const int N = 1e6 + 10, M = 25;
int dx[] = {-1, -1, -1, 1, 1, 1}, dy[] = {-1, 0, 1, -1, 0, 1};
map<pii, bool> mp;
void solve()
{
    ll n, q, tc;
    cin >> n >> q >> tc;
    vector<ll> t(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> t[i];
    sort(t.begin() + 1, t.end());
    for (int i = 1; i <= n; i++)
        t[i] += t[i - 1];
    ll ans = t[n] + tc;
    for (int i = 1; i <= q; i++)
    {
        ll m;
        cin >> m;
        auto chk = [&](int x)
        {
            ll r = tc * (n - x);
            return r <= m;
        };
        int l = 0, r = n;
        while (l < r)
        {
            int mid = l + r >> 1;
            if (chk(mid))
                r = mid;
            else
                l = mid + 1;
        }
        cout << t[l] + tc << endl;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--)
        solve();
    return 0;
}

D

考虑答案不多,暴力预处理出所有答案

数组的第一个和第二个元素中,至少存在一个\(\le \sqrt{10^9}\)

按照这个枚举即可

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
#define ls(x) (a[x].l)
#define rs(x) (a[x].r)
#define sum(x) a[x].sum
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 1e9 + 7;
const int N = 7e7 + 10, M = 25;
random_device rd;
mt19937_64 gen(rd());
void solve()
{
    map<ll, bool> mp;
    int n, q;
    cin >> n >> q;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> a[i], mp[a[i]] = 1;
    set<ll> s;
    ll B = sqrt(2e9);

    auto chk = [&](ll x)
    {
        if (mp[-x])
        {
            s.insert(0);
            return;
        }
        ll res = 1;
        for (int i = 1; i <= n; i++)
        {
            res *= (a[i] + x);
            if (abs(res) > 1e9)
                return;
        }
        s.insert(res);
    };

    for (int i = -B; i <= B; i++)
        for (int j = 1; j <= 2; j++)
            chk(i - a[j]), chk(-i - a[j]);
    while (q--)
    {
        ll x;
        cin >> x;
        cout << (s.find(x) != s.end() ? "Yes" : "No") << endl;
    }
}
int main()
{
    // cout << setprecision(5);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--)
        solve();
    return 0;
}

E

爆搜答案

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 998244353;
const int N = 1e6 + 10, M = 25;

void solve()
{
    int n, m;
    cin >> n >> m;
    vector<ll> a(n + 1, 0);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    vector<pii> race(m);
    for (auto &[u, v] : race)
        cin >> u >> v;
    int ans = n;
    vector<int> path(m + 1, 0);
    auto dfs = [&](const auto &dfs, int u) -> void
    {
        if (u == m)
        {
            vector<ll> b = a;
            for (int i = 0; i < m; i++)
            {
                auto [u, v] = race[i];
                if (path[i] == 1)
                    b[u] += 3;
                else if (path[i] == 2)
                    b[v] += 3;
                else
                    b[u]++, b[v]++;
            }
            int res = 0;
            for (int i = 2; i <= n; i++)
                if (b[i] > b[1])
                    res++;
            ans = min(ans, res + 1);
            return;
        }
        for (int i = 1; i <= 3; i++)
        {
            path[u] = i;
            dfs(dfs, u + 1);
        }
    };
    dfs(dfs, 0);
    cout << ans << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    cin >> _;
    while (_--)
        solve();
    return 0;
}

F

把题意抽象出来就是第二类斯特林数板子

```cpp
void solve()
{
    vector<ll> fac(N), invfac(N);
    auto qmi = [&](ll a, ll b) -> ll
    {
        ll res = 1;
        while (b)
        {
            if (b & 1)
                res = res * a % mod;
            b >>= 1;
            a = a * a % mod;
        }
        return res;
    };
    auto init = [&](int n)
    {
        fac[0] = 1;
        for (int i = 1; i <= n; i++)
            fac[i] = fac[i - 1] * i % mod;
        invfac[n] = qmi(fac[n], mod - 2);
        for (int i = n - 1; i >= 0; i--)
            invfac[i] = invfac[i + 1] * (i + 1) % mod;
    };
    auto C = [&](int n, int m)
    {
        return fac[n] * invfac[m] % mod * invfac[n - m] % mod;
    };

    int n, m;
    cin >> n >> m;
    init(1e5);
    ll ans = 0;
    for (int i = 0; i <= m; i++)
    {
        ll res = (i & 1) ? -1 : 1;
        res = res * C(m, i) % mod;
        res = res * qmi(m - i, n) % mod;
        ans = (ans + res + mod) % mod;
    }
    ans = ans * invfac[m] % mod;
    cout << ans << endl;
}

G

将优惠卷按优惠幅度排序,枚举能用哪些,能用大的就一定能用小的

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 998244353;
const int N = 1e6 + 10, M = 25;

void solve()
{
    ll n, m;
    cin >> n >> m;
    vector<pll> a(n);
    for (auto &[x, y] : a)
        cin >> x >> y;
    sort(a.begin(), a.end());
    ll ans = m, sum = 0;
    for (auto [x, y] : a)
    {
        sum += y;
        if (m + sum >= x)
            ans = max(ans, m + sum);
    }
    cout << ans << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    cin >> _;
    while (_--)
        solve();
    return 0;
}

H

贪心,考虑将某一位1变成0,后面就可以全是1了

比如:\((110110)_2\)可以变成\((101111)_2\)

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 998244353;
const int N = 1e6 + 10, M = 25;
random_device rd;        // 将用于为随机数引擎获得种子
mt19937_64 gen(time(0)); // 以播种标准 mersenne_twister_engine
void solve()
{
    ll n, m, ans = 0;
    bool st = 0;
    cin >> n >> m;
    vector<pll> a(n);
    for (auto &[x, y] : a)
        cin >> x >> y;
    auto cal = [&](ll t) -> ll
    {
        ll res = 0;
        for (auto [x, y] : a)
            if ((t | y) == t)
                res += x;
        return res;
    };
    ans = cal(m);
    for (int i = 40; i >= 0; i--)
        if ((m >> i) & 1)
        {
            ll res = m;
            res ^= (1ll << i);
            for (int j = i - 1; j >= 0; j--)
                res |= (1ll << j);
            ans = max(ans, cal(res));
        }
    cout << ans << endl;
}

int main()
{
    cout << setprecision(5);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    cin >> _;
    while (_--)
        solve();
    return 0;
}

I

模拟可以发现方案二的点会集中靠近圆心,而方案一是均匀的。

根据这条性质可以找到一个差异较大的边界,直接判断距离即可

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 998244353;
const int N = 1e6 + 10, M = 25;
 
void solve()
{
    int n, cnt = 0;
    cin >> n;
    vector<pll> p(n);
    for (auto &[x, y] : p)
        cin >> x >> y;
    vector<ll> dist(n);
    for (auto [x, y] : p)
    {
 
        if (abs(x) <= 70 && abs(y) <= 70)
            cnt++;
    }
    cout << (cnt >= 75000 ? "buaa-noob" : "bit-noob") << endl;
}
int main()
{
    cout << setprecision(5);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--)
        solve();
    return 0;
}

J

一log做法:

二分答案

因为每个位置一定有人去,所有最后两人的位置一定是\(a[j],a[n]\),这样可以贪心的倒着找到最小的\(j\),满足\(abs(a[j]-a[n])\le mid\),然后就递归的变成的一个子问题了。

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
#define ls(x) (a[x].l)
#define rs(x) (a[x].r)
#define sum(x) a[x].sum
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 1e9 + 7;
const int N = 7e7 + 10, M = 25;
random_device rd;
mt19937_64 gen(rd());
void solve()
{
    int n, x, y;
    cin >> n;
    n += 2;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    auto chk = [&](int t) -> bool
    {
        int idx = n;
        while (idx > 1)
        {
            int pos = idx;
            int mx = a[pos], mi = a[pos];
            for (int i = idx - 1; i >= 1; i--)
            {
                if (abs(mx - a[i]) <= t && abs(mi - a[i]) <= t)
                    idx = i;
                mx = max(mx, a[i]), mi = min(mi, a[i]);
            }
            if (idx == pos)
                return false;
        }
        return true;
    };
    int l = abs(a[1] - a[2]), r = 1e9;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (chk(mid))
            r = mid;
        else
            l = mid + 1;
    }
    cout << l << endl;
}
int main()
{
    // cout << setprecision(5);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--)
        solve();
    return 0;
}

二log做法:

用set处理出每个点的所有可能性,只要每个点都不为空,就一定存在一种满足的方案

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
#define ls(x) (a[x].l)
#define rs(x) (a[x].r)
#define sum(x) a[x].sum
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 1e9 + 7;
const int N = 7e7 + 10, M = 25;
random_device rd;
mt19937_64 gen(rd());
void solve()
{
    int n, x, y;
    cin >> n >> x >> y;
    vector<int> a(n);
    for (int i = 0; i < n; i++)
        cin >> a[i];
    auto chk = [&](int t) -> bool
    {
        int lst = y;
        set<int> s;
        if (abs(x - y) <= t)
            s.insert(x);
        for (auto pos : a)
        {
            if (s.size() && abs(pos - lst) <= t)
                s.insert(lst);
            while (s.size() && abs(*s.begin() - pos) > t)
                s.erase(s.begin());
            while (s.size() && abs(*s.rbegin() - pos) > t)
                s.erase(*s.rbegin());
            lst = pos;
            if (s.empty())
                return false;
        }
        return true;
    };
    int l = abs(x - y), r = 1e9;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (chk(mid))
            r = mid;
        else
            l = mid + 1;
    }
    cout << l << endl;
}
int main()
{
    // cout << setprecision(5);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--)
        solve();
    return 0;
}

K

把题目按照\(i\)\(a[i]\)连边,会形成若干内向基环树和链,并且答案取决于环,随机选环上一点,枚举并检查答案的正确性(排列复合仍为排列,所以只要一点确定,其他点也就确定了),最后将答案乘起来

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 998244353;
const int N = 2e5 + 100, M = 25;
void solve()
{
    ll n, ans = 1;
    cin >> n;
    vector<string> s(n + 1);
    vector<int> a(n + 1), d(n + 1, 0), vis(n + 1, 0);
    vector<vector<int>> rec(n + 1, vector<int>(6, 0));
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i] >> s[i];
        d[a[i]]++;
    }
    queue<int> q;
    for (int i = 1; i <= n; i++)
        if (!d[i])
            q.push(i);
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        vis[t] = 1;
        if (--d[a[t]] == 0)
            q.push(a[t]);
    }
    for (int i = 1; i <= n; i++)
        if (!vis[i])
        {
            ll res = 0;
            for (int j = i; !vis[j]; j = a[j])
                vis[j] = 1;
            for (int j = 0; j < 5; j++)
            {
                ll u = i, v = j;
                while (!rec[u][v])
                {
                    rec[u][v] = 1;
                    v = s[u][v] - 'A', u = a[u];
                    if (u == i)
                        break;
                }
                if (u == i && v == j)
                    res++;
            }
            ans = ans * res % mod;
        }
    cout << ans << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--)
        solve();
    return 0;
}

L

结论赛时猜的

当光源高度低于2h时,俯视图中墙一定在三角形的中位线上

高于2h是,阴影到达不了边界,一定变小

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 998244353;
const int N = 1e6 + 10, M = 25;

void solve()
{
    db c, d, h, w;
    cin >> c >> d >> h >> w;
    cout << 3 * w * c << endl;
}
int main()
{
    cout << setprecision(10);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
     cin >> _;
    while (_--)
        solve();
    return 0;
}

M

手动模拟一下,答案显然

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 998244353;
const int N = 1e6 + 10, M = 25;

void solve()
{
    ll n;
    cin >> n;
    cout << (n / 6) * (n % 6 != 0 ? 2 : 1) << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    cin >> _;
    while (_--)
        solve();
    return 0;
}
posted @ 2024-02-09 20:32  0x3ea  阅读(4)  评论(0编辑  收藏  举报