1. 程式人生 > 其它 >2022.4.8

2022.4.8

Codeforces Round #781 (Div. 2)

A. GCD vs LCM

啊,太久沒接觸最小公倍數了腦子抽了相成了最大公倍數,導致搞了很久。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,INF=1e9;
int main()
{
    cin.tie(nullptr)->sync_with_stdio(false);
    int t;
    cin >> t;
    while(t--)
    {
        ll n;
        cin >> n;
        if(n%4==0)
        {
            ll x = n / 4;
            cout << x << ' ' << x << ' ' << x << ' ' << x << '\n';
        }
        else 
        {
                n -= 2;
                ll x = n / 2;
                if(n&1)
                {
                    cout << x << ' ' << x + 1<<' ' ;
                }
                else
                    cout << x-1 << ' ' << x+1 << ' ';
                cout << "1 1" << '\n';
        }
    }

    return 0;
}

B. Array Cloning Technique

呃呃,如果要把一個數組變成全部一樣且操作次數最少的話,肯定得挑相同元素最多的那個,每次複製我們可以使原來元素的個數翻倍,然後再swap過去,花費1+x次,不斷重複這個過程直到全部交換完

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,INF=1e9;
int a[N];
int main()
{
    cin.tie(nullptr)->sync_with_stdio(false);
    int t;
    cin >> t;
    while(t--)
    {
        int n;
        map<int, int> mp;
        cin >> n;
        for (int i = 1; i <= n;i++)
        {
            cin >> a[i];
            mp[a[i]]++;
        }
        int cnt = 0;
        for (int i = 1; i <= n;i++)
        {
            cnt = max(cnt, mp[a[i]]);
        }
        int res = n - cnt;
        if(res==0)
        {
            cout << 0 << '\n';
        }
        else
        {
            int ans = 0;
            while(cnt<n)
            {
                if(cnt+cnt>n)
                {
                    ans += 1 + n - cnt;
                    break;
                }
                ans += (1 + cnt);
                cnt += cnt;
            }
            cout << ans << '\n';
        }
    }
      
    return 0;
}

C. Tree Infection

貪心題,但是寫著寫著胡思亂想了,看了題解可以用二分來貪心,首先肯定得先感染兒子最多的,感染其中一個兒子剩下的每次都可以感染一個,二分感染的時間,同時對於每個兒子集合,從大到小排序然後求出能感染兒子的,對於第i個被感染的,剩下的能在mid時間內感染mid-i個,然後還需要加上而外感染的和一開始感染的第一個點。即mid>=cnt+ans

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2e5+10,INF=1e9;
vector<int> p[N];
int q[N],cnt;
bool check(int mid)
{
    int ans = 0;
    for (int i = 1; i <= cnt;i++)
    {
        if(q[i]-(mid-i)>0)
        {
            ans += q[i]-(mid-i);
        }
    }
    return mid >= ans + cnt;
}
bool cmp(int a,int b)
{
    return a > b;
}
int main()
{
    cin.tie(nullptr)->sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin >> n;
        for (int i = 1; i <= n;i++)
        {
            p[i].clear();
            q[i] = 0;
        }
        for (int i = 2; i <= n;i++)
        {
            int x;
            cin >> x;
            p[x].push_back(i);
        }
        cnt = 1;
        for (int i = 1; i <= n;i++)
        {
            if(p[i].size())
                q[++cnt] = p[i].size() - 1;
        }
        sort(q + 1, q + 1 + cnt, cmp);
        int l = 1, r = n;
        while(l<r)
        {
            int mid = l + r >> 1;
            if(check(mid))
            {
                r = mid;
            }
            else
                l = mid + 1;
        }
        cout << l << '\n';
    }

    return 0;
}