20220219寒假学校周赛


title: 2022寒假周赛4
date: 2020-02-19
tags: ACM

A.直角三角形

知识点:二分

思路:直角三角形肯定是三角形,所以只需要判断 a 2 + b 2 = c 2 a^2+b^2=c^2 a2+b2=c2。设三边变成分别为a,b,c(c>a,b)所以可知
{ a 2 + b 2 = k 2 ( k > a , b ) a 2 + k 2 = b 2 ( b > a , k ) \begin{cases} a^2+b^2=k^2 (k>a,b)\\[2ex] a^2+k^2=b^2 (b>a,k) \end{cases} a2+b2=k2(k>a,b)a2+k2=b2(b>a,k)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

const int N = 1e5 + 5;

LL a[N], b[N];

int main()
{
    int n, k;
    while (cin >> n >> k)
    {
        rep(i, 0, n)
        {
            cin >> a[i];
            b[i] = a[i] * a[i];
        }
        int ans = k;
        int k2 = k * k;
        per(i, n - 1, -1)
        {
            LL t = abs(k2 - b[i]);
            int p = lower_bound(b, b + n, t) - b;
            if (p != n && b[p] == t)
            {
                ans += a[i] + a[p];
                break;
            }
        }
        if (ans > k)
            cout << ans << endl;
        else
            cout << "no" << endl;
    }
    return 0;
}

B.数学题

知识点:逆元

思路:勉强过了[doge]

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

const LL N = 1e6 + 5, MOD = 1e9 + 7;

LL a[N];

LL qpow(LL a, LL b)
{
    LL ans = 1;
    while (b)
    {
        if (b & 1)
            ans = ans * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return ans;
}

int main()
{
    int n, q;
    while (cin >> n >> q)
    {
        LL ans = 1;
        rep(i, 1, n + 1)
        {
            cin >> a[i];
            ans = ans * a[i] % MOD;
        }
        while (q--)
        {
            LL x, y;
            cin >> x >> y;
            ans = ans * qpow(a[x], MOD - 2) % MOD * y % MOD;
            a[x] = y;
            cout << ans << endl;
        }
    }
    return 0;
}

C.品酒大师(未补)

知识点:拓扑排序

思路:


D.帮派

知识点:并查集

思路:当a和b为兄弟时,直接合并;一个二位数组f存1~n之间每个人各自的敌人id,然后合并fi使f[i][0]和f[i]中的其他的敌人合并。其实我们每次合并的都是f[i][0]和f[i]其他敌人,我们可以在输入时判断当前f[a]是第一次输入,那么我们就使f[a]=b,不然我们就使f[a]和b合并,同理f[b]也是。

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

const int N = 1e3 + 5;

int fa[N], ans, fd[N];

void init(int n)
{
    rep(i, 1, n)
    {
        fa[i] = i;
        fd[i] = 0;
    }
}

int find(int x)
{
    return x == fa[x] ? x : (fa[x] = find(fa[x]));
}

void merge(int x, int y)
{
    int tx = find(x), ty = find(y);
    if (tx != ty)
    {
        fa[tx] = ty;
        ans--;
    }
}

int main()
{
    int n, m;
    while (cin >> n >> m)
    {
        init(n + 1);
        ans = n;
        while (m--)
        {
            char c;
            int a, b;
            cin >> c >> a >> b;
            if (c == 'F')
                merge(a, b);
            else if (c == 'E')
            {
                if (fd[a])
                    merge(fd[a], b);
                else
                    fd[a] = b;
                if (fd[b])
                    merge(fd[b], a);
                else
                    fd[b] = a;
            }
        }
        cout << ans << endl;
    }
    return 0;
}

E.增增减减

知识点:贪心

思路:使数组a中最大的减,那么只可能出现两种结果,第一种就是全部值

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

int main()
{
    int n;
    while (cin >> n)
    {
        LL s = 0;
        rep(i, 0, n)
        {
            LL t;
            cin >> t;
            s += t;
        }
        LL ans = n - (s % n != 0);
        cout << ans << endl;
    }
    return 0;
}

F.制作字符串

知识点:贪心、暴力

思路:对数组a从小到大排序,并做一个桶数组p,如果ai出现在p中,那么使 a i a_i ai减1,直到ai==0或者从未出现

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

const int N = 1e5 + 5;
LL a[N];

LL solve(int n)
{
    map<LL, bool> mp;
    sort(a, a + n);
    LL ans = 0;
    rep(i, 0, n)
    {
        int t = a[i];
        if (!mp[t])
        {
            ans += t;
            mp[t] = true;
        }
        else
            per(i, t, -1)
            {
                if (!mp[i])
                {
                    ans += i;
                    mp[i] = true;
                    break;
                }
            }
    }
    return ans;
}

int main()
{
    int n;
    while (cin >> n)
    {
        rep(i, 0, n) cin >> a[i];
        cout << solve(n) << endl;
    }
    return 0;
}

G.纸飞机

知识点:贪心

思路:每个人制作n架纸飞机需要(n+s-1)/s张白纸t,那么所有人需要k*t张白纸w,那么需要(w+p-1)/p包纸

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

int main()
{
    int k, n, s, p;
    while (cin >> k >> n >> s >> p)
    {
        int t = (n / s + (n % s != 0)) * k;
        int ans = t / p + (t % p != 0);
        cout << ans << endl;
    }
    return 0;
}

H.生日礼物

知识点:贪心

思路:最多的送礼方式是1 2 1这样子送,所以最多可以送(n+2)/3*2次

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

int main()
{
    int n;
    while (cin >> n)
    {
        int ans = n / 3 * 2 + (n % 3 != 0);
        cout << ans << endl;
    }
    return 0;
}

I.字符串操作

知识点:模拟

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

const int N = 1e5 + 5;

int main()
{
    string s;
    int q;
    while (cin >> s >> q)
    {
        while (q--)
        {
            string t, s1, s2;
            int a, b, c, d;
            cin >> t;
            if (t == "Append")
            {
                cin >> s1;
                s += s1;
            }
            else if (t == "Insert")
            {
                cin >> a >> s1;
                s.insert(a - 1, s1);
            }
            else if (t == "Swap")
            {
                cin >> a >> b >> c >> d;
                a -= 1, b -= 1, c -= 1, d -= 1;
                s1 = s.substr(c, d - c + 1);
                s2 = s.substr(a, b - a + 1);
                s.erase(c, d - c + 1),s.erase(a, b - a + 1);
                s.insert(a, s1);
                if (s1.size() > s2.size())
                {
                    int t = s1.size() - s2.size();
                    c += t;
                    d += t;
                }
                else if (s1.size() < s2.size())
                {
                    int t = s2.size() - s1.size();
                    c = max(c - t, 0);
                    d = max(d - t, 0);
                }
                s.insert(c, s2);
            }
            else if (t == "Reverse")
            {
                cin >> a >> b;
                a -= 1, b -= 1;
                s2 = s;
                while (b > a)
                {
                    s[a] = s2[b];
                    s[b] = s2[a];
                    a++, b--;
                }
            }
        }
        cout << s << endl;
    }
    return 0;
}

J.最后一关

知识点:逻辑

思路:我yjw好后悔没做。。。

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define isLeap(year) (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
#define endl '\n'

int a[3];
map<string, bool> mp;

void solve(int y, int m, int d)
{
    if (m > 12 || m < 1 || d > 31 || d < 1)
        return;
    y = y <= 59 ? 2000 + y : 1900 + y;
    if (m == 2 && d >= 29)
    {
        if (!(d == 29 && isLeap(y)))
            return;
    }
    string sm = m < 10 ? "0" + to_string(m) : to_string(m);
    string sd = d < 10 ? "0" + to_string(d) : to_string(d);
    string res = to_string(y) + "-" + sm + "-" + sd;
    mp[res] = true;
}

int main()
{
    while (scanf("%d/%d/%d", &a[0], &a[1], &a[2]) != EOF)
    {
        solve(a[0], a[1], a[2]);
        solve(a[2], a[0], a[1]);
        solve(a[2], a[1], a[0]);
        for (auto i = mp.begin(); i != mp.end(); i++)
            cout << i->first << endl;
        mp.clear();
    }
    return 0;
}

K.密钥格式化

知识点:模拟题

思路:从后往前

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

const int N = 1e5 + 5;

string solve(string s, int n)
{
    string ans = "", t = "";
    int len = s.size();
    per(i, len - 1, -1)
    {
        if (s[i] != '-')
        {
            if (islower(s[i]))
                s[i] = toupper(s[i]);
            t = s[i] + t;
            if (t.size() == n)
            {
                if (ans != "")
                    ans = "-" + ans;
                ans = t + ans;
                t = "";
            }
        }
    }
    if (t != "")
        ans = t + "-" + ans;
    return ans;
}

int main()
{
    string s;
    int n;
    while (cin >> s >> n)
        cout << solve(s, n) << endl;
    return 0;
}

L.命悬一线独木桥

知识点:前缀和

思路:根据题目要求,需要使 a 0 + a 1 + . . . + a ( i − 1 ) = = a ( i + 1 ) + a ( i + 2 ) + . . . + a ( n ) a_0+a_1+...+a_(i-1)==a_(i+1)+a_(i+2)+...+a_(n) a0+a1+...+a(i1)==a(i+1)+a(i+2)+...+a(n)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

const int N = 1e5 + 5;

LL a[N];

int solve(int n)
{
    if (n == 1)
        return 1;
    rep(i, 1, n)
    {
        if (a[i - 1] == a[n - 1] - a[i])
            return i;
    }
    return -1;
}

int main()
{
    int n;
    while (cin >> n)
    {
        rep(i, 0, n)
        {
            cin >> a[i];
            if (i != 0)
                a[i] += a[i - 1];
        }
        cout << solve(n) << endl;
    }
    return 0;
}

M.算式接龙

知识点:DFS

思路:使用stringsteam处理输入,使“±*/”分别用数字31-34表示,注意除数不能为零。。

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'

const int N = 15;

string sign = "+-*/";
int n, m, k,a[N][N],vis[N][N];
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

bool dfs(int x, int y, int p, int ans, int len)
{
    if (ans == k)
        return true;
    rep(i, 0, 4)
    {
        int tx = x + dir[i][0], ty = y + dir[i][1];
        if (tx < 0 || tx >= n || ty < 0 || ty >= m || vis[tx][ty])
            continue;
        int val = a[tx][ty], t = ans;
        vis[tx][ty] = 1;
        if (val < 30 && p > 30)
        {
            if (p == 31)
                t += val;
            else if (p == 32)
                t -= val;
            else if (p == 33)
                t *= val;
            else if (val == 0)
            {
                vis[tx][ty] = 0;
                continue;
            }
            else
                t /= val;
            if (dfs(tx, ty, 0, t, len + 1))
                return true;
        }
        if (val > 30 && p < 30)
            if (dfs(tx, ty, val, t, len + 1))
                return true;
        vis[tx][ty] = 0;
    }
    return false;
}

bool solve()
{
    rep(i, 0, n)
    {
        rep(j, 0, m)
        {
            if (a[i][j] < 30)
            {
                vis[i][j] = 1;
                if (dfs(i, j, 0, a[i][j], 1))
                    return true;
                vis[i][j] = 0;
            }
        }
    }
    return false;
}

int main()
{
    stringstream ss;
    while (cin >> n >> m)
    {
        rep(i, 0, n)
        {
            rep(j, 0, m)
            {
                string s;
                cin >> s;
                if (ispunct(s[0]) && s.size() == 1)
                {
                    int k = 0;
                    for (k = 0; k < 4; k++)
                        if (s[0] == sign[k])
                            break;
                    a[i][j] = 31 + k;
                }
                else
                {
                    ss.str(s);
                    ss >> a[i][j];
                    ss.clear();
                }
            }
        }
        cin >> k;
        if (solve())
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值