补题集合2

VJ

409组队赛2

C - Find a Number
没想到这是一个签到题,因为数据量小,状态并不多,所以可以使用 b f s bfs bfs 去跑每一个状态。令 m o d mod mod 是余数, s u m sum sum 是累加和,那么状态最多就只有 500 ∗ 5000 500 * 5000 5005000 种状态。可以 b f s bfs bfs
但是要注意的地方是, b f s bfs bfs 在标记是否遍历过时,应在入队的时候就进行标记,而不是在出队的时候再进行标记,不然会重复入队造成 M L E MLE MLE 或者 T L E TLE TLE
代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N = 500+5;
typedef pair<int, int>PII;
int T, n, m;
bool st[N][N*10];
struct node
{
    int mod, s;
    string ans;
};
queue<node>q;
string bfs()
{
    q.push({0, 0, ""});
    st[0][0] = true;
    while(q.size())
    {
        int t1 = q.front().mod, t2 = q.front().s;
        string s = q.front().ans;
        q.pop();
        if(t1 == 0 && t2 == m) return s;
        for(int i = 0; i < 10; i ++)
        {
            int z1 = (t1*10 + i) % n, z2 = t2 + i;
            if(z2 <= m && !st[z1][z2])
            {
                st[z1][z2] = true;
                q.push({z1, z2, s + (char)(i + '0')});
            }
        }
    }
    return "-1";
}
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n >> m;
    cout << bfs() << '\n';
}

H - Tower
这个题实属没想到可以这样暴力写
来源作者:owooooow
代码如下:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int Max = 0x3f3f3f3f3f3f3f3f;
const int Min = -0x3f3f3f3f3f3f3f3f;
const int N = 2e5+5;
typedef pair<int, int>PII;
int T, n, m;
int q[N], a[N];

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> T;
    while(T --)
    {
        set<int>se;
        cin >> n >> m;
        for(int i = 0; i < n; i ++)
        {
            cin >> a[i];
            int x = a[i];
            while(x)
            {
                se.insert(x);
                x /= 2;
            }
        }
        int ans = Max;
        for(auto it : se)
        {
            int cnt = 0, res = 0;
            for(int i = 0; i < n; i ++)
            {
                if(a[i] <= it) q[cnt ++] = it - a[i];
                else
                {
                    int x = a[i], tt = 0;
                    while(x / 2 >= it)
                    {
                        tt ++;
                        x /= 2;
                    }
                    tt += min(abs(it - x), 1 + it - x / 2);
                    q[cnt ++] = tt;
                }
            }
            sort(q, q+cnt);
            for(int i = 0; i < cnt - m; i ++)
            {
                res += q[i];
            }
            ans = min(ans, res);
        }
        cout << ans << '\n';
    }
}

牛客

第十一届"图灵杯"NEUQ-ACM程序设计竞赛

古希腊掌管原神的神
这个题出的是真烂啊,题目也并没有说明,我们知不知道谁是真神或者是假神什么的。这个题最关键的一点就在于我们并不知道自己问的神他是真还是假还是变化神。所以只有当真神数量大于假神和变化神数量之和时,才能确定哪个是原神。因为在最坏的清况下我们问的 b + c b + c b+c 个神说的都是假话,假设都说原神是 x x x 吧;剩下的都是真神了,当再问 b + c + 1 b + c + 1 b+c+1 个神之后,都说原神是 y y y,这时候根据数量的大小,就能辨别哪一个是原神了。
最后再特判一下当只有一个神的时候,一次也不用问就可以确定。
代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
typedef pair<int, int>PII;
int T, n, m;

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int a, b, c;
    cin >> a >> b >> c;
    if(a + b + c == 1)
    {
        cout << "YES\n";
        cout << 0 << '\n';
        return 0;
    }
    if(a > b + c)
    {
        cout << "YES\n";
        cout << (b+c)*2+1 << '\n';
        return 0;
    }
    cout << "NO\n";
    return 0;
}

牛客小白月赛88

多重映射
这个题,看完题解后就恍然大悟了,当时时间不多了,也没仔细想。这个题要倒着考虑,从后向前做一个并查集就可以了。例如 7 7 7 5 5 5 然后 5 5 5 3 3 3,那么就让 p [ 5 ] = 3 , p [ 7 ] = p [ 5 ] p[5] = 3,p[7] = p[5] p[5]=3p[7]=p[5]
唯一要注意的地方就是,这个是多组输入,不能每次都用 m e m s e t memset memset 来进行初始化,题解是用 m a p map map 处理,但是可以直接把出现的数字存入 v e c t o r vector vector 中,只对 v e c t o r vector vector 内的数字初始化就可以了,但是记得每次清空 v e c t o r vector vector
注意把数组大小开到 1 0 6 10^6 106
代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
typedef pair<int, int>PII;
int T, n, m;
int a[N], f[N];
PII p[N];
vector<int>v;
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> T;
    while(T --)
    {
        cin >> n >> m;
        for(int i = 0; i < n; i ++)
        {
            cin >> a[i];
        }
        for(int i = 0; i < m; i ++)
        {
            int x, y;
            cin >> x >> y;
            p[i] = {x, y};
            v.push_back(x), v.push_back(y);
        }
        for(int i = m - 1; i >= 0; i --)
        {
            int t1 = p[i].first, t2 = p[i].second;
            if(f[t2] != 0) f[t1] = f[t2];
            else f[t1] = t2;
        }
        for(int i = 0; i < n; i ++)
        {
            if(f[a[i]]) cout << f[a[i]];
            else cout << a[i];
            if(i != n - 1) cout << " ";
            else cout << '\n';
        }
        for(auto it : v) f[it] = 0;
        v.clear();
    }
    return 0;
}
  • 15
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值