AcWing:第72场周赛

131 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

AcWing——第72场周赛

4624. 最小值 - AcWing题库

问题解析

直接比较a,b,(a+b)/3的大小,输出最小的即可。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>#pragma GCC optimize(2)
#pragma GCC optimize(3)#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 4e5 + 50;
​
void solve()
{
    int a, b, c;
    cin >> a >> b;
    c = (a + b) / 3;
    cout << min(a, min(b, c)) << endl;
}
​
signed main()
{
​
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t = 1;
    cin >> t;
​
    while (t--)
    {
        solve();
    }
    return 0;
}

4625. 压缩文件 - AcWing题库

问题解析

贪心。

先计算一下一个都不压缩需要的空间sum,然后看是不是小于等于m,如果是,说明一个都不压缩也能放得下,输出0。不然,我们用一个数组,记录bi-ai的值,即将这个文件压缩后能节省的空间。并对他们降序排序。每次取能节省最多的文件来压缩:sum-(ai-bi)。压缩到sum小于m为止。如果所有文件都压缩了,sum还是大于m,输出-1。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>#pragma GCC optimize(2)
#pragma GCC optimize(3)#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 4e5 + 50;
​
void solve()
{
    int n, m, sum = 0, cnt = 0, x, y;
    cin >> n >> m;
    vector<int>v(n);
    for (int i = 0; i < n; i++)
    {
​
        cin >> x >> y;
        sum += x;
        v[i] = x - y;
    }
    sort(v.begin(), v.end(), greater<int>());
    int idx = 0;
    while (idx<n&&sum > m)
    {
        sum -= v[idx++];
        cnt++;
    }
    if (sum <= m)cout << cnt;
    else cout << -1;
}
​
signed main()
{
​
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t = 1;
    //cin >> t;
​
    while (t--)
    {
        solve();
    }
    return 0;
}

4626. 最小移动距离 - AcWing题库

问题解析

我心态爆炸,因为没有判断当前点是否走过,一直t在最后一个测试例。

这题的意思就是:判断这些点是否都能组成一个个的环,如果是就输出这些环的长度的最小公倍数,反之输出-1

然后就是正常的建单向图,如果有ai等于i的情况,我们直接记录这个环的大小是1即可。

再dfs求得每个环的大小:记录递归的次数,如果重复走到起点,说明成环,如果不成环,返回0。

  • 如果返回0,说明不是所有的点都能组成环,输出-1.
  • 如果返回偶数,那么环的大小要减半。比如1->2->3->4->1,那么1的目标点就可以是3,而不非要是自己,所以路径大小减半。
  • 如果返回奇数,直接记录下来。

然后对所有记录的环的大小,求他们的最小公倍数。

AC代码

//求最大公约数
int gcd(int a, int b) 
{
    return b==0?a:gcd(b, a % b);
}
​
int n;
//存图,其实不用这么麻烦,主要是习惯
vector<int>tree[N];
//记录这个点是否走过
bool st[150];
//x是当前点,y是起点,len是递归次数
int dfs(int x, int y, int len)
{
    int z = 0;
    if (x == y && len != 0)
    {
        return len;
    }
    //因为除了起点以外,每个点都只可能走一次,如果这个点不是起点还走了两次,必定不是环
    if (st[x] && x != y)return 0;
    st[x] = true;
    for (auto i : tree[x])
    {
        z = dfs(i, y, len + 1);
    }
    return z;
}
void solve()
{
    int x;
    cin >> n;
    vector<int>res;
    for (int i = 1; i <= n; i++)
    {
        cin >> x;
        if (x != i)
            tree[i].push_back(x);
        else
        {
            res.push_back(1);
            st[i] = true;
        }
    }
​
    for (int i = 1; i <= n; i++)
    {
        //如果当前点没有走过,那么它可以当作环的起点
        if (st[i] == false)
        {
            //求环长
            int ans = dfs(i, i, 0);
            //不是环,输出-1
            if (ans == 0)
            {
                cout << -1 << endl;
                return;
            }
            else
            {
                //偶数长度要减半
                if (ans % 2 == 0)ans /= 2;
                res.push_back(ans);
            }
        }
    }
    //计算最小公倍数
    x = 1;
    for (auto i : res)
    {
        x = x / gcd(max(i, x), min(i, x)) * i;
    }
    cout << x;
}