Codeforces Round #601 (Div. 2)題解 by_Hile

前言:前幾天晚上打了一場Div1+2後終於上藍,爲了紀念,這周就寫這一場的題解了。

題目鏈接


A.Changing Volume

水題,貪心。優先移動5格,然後2格,最後1格。

#include<bits/stdc++.h>
using namespace std;
int T,x,y;
int main()
{
    cin>>T;
    while(T--)
    {
        cin>>x>>y;
        if(y<x)swap(x,y);
        if(x==y)cout<<0<<"\n";
        else
        {
            int tt=(y-x)/5;
            cout<<(tt+(y-x-tt*5)/2+(y-x-tt*5)%2)<<"\n";
        }
    }
}

B.Fridge Lockers

水題。當點數不小於邊數時,若要使每個點至少連兩個邊,只能形成一個大環。

#include<bits/stdc++.h>
using namespace std;
int T,n,m,a;
int main()
{
    cin>>T;
    while(T--)
    {
        int sum=0;
        cin>>n>>m;
        for(int i=1;i<=n;i++)cin>>a,sum+=a;
        if(n==2||m<n)
        {
            cout<<-1<<"\n";
            continue;
        }
        else cout<<sum*2<<"\n";
        for(int i=0;i<n;i++)
            cout<<(i)%n+1<<" "<<(i+1)%n+1<<"\n";
    }
}


C.League of Leesins

觀察發現當n5n\geq 5時,11nn只存在於一個三元組,22n1n-1只存在於兩個三元組,其他元素都存在於三個三元組。所以可以記錄每個數字的出現次數和所屬的三元組,然後從出現次數爲11的數字所載的三元組開始刪除(出現次數–),然後尋找下一個出現11次的數,刪除順序就是答案。時間複雜度O(n)O(n)

注意刪到最後會出現一個次數爲1,1,11,1,1的三元組,此時應根據其最初出現次數由大到小放進答案,否則親身試驗會WA2(

#include<bits/stdc++.h>
#define N 100010
using namespace std;
int T,n,m,a[N],vis[N],pre[N],v[N];
int t[N][3];
vector<int> G[N],ans;
bool cmp(int a,int b)
{
    return pre[a]>pre[b];
}
void dfs(int x)
{
    if(vis[x]==1)
    {
        ans.push_back(x);
        for(int j=0;j<G[x].size();j++)
        {
            if(v[G[x][j]])continue;
            int* tmp=t[G[x][j]];
            v[G[x][j]]=1;
            if(vis[tmp[0]]==1&&vis[tmp[1]]==1&&vis[tmp[2]]==1)
            {
                ans.pop_back();
                sort(tmp,tmp+3,cmp);
                for(int k=0;k<3;k++)
                    ans.push_back(tmp[k]);
                for(int k=0;k<n;k++)cout<<ans[k]<<" ";
                exit(0);
            }
            for(int i=0;i<3;i++)vis[tmp[i]]--;
            for(int i=0;i<3;i++)dfs(tmp[i]);
        }
    }
}
int main()
{
    cin>>n;
    for(int i=1;i<=n-2;i++)
        for(int j=0;j<3;j++)
        {
            cin>>t[i][j];
            vis[t[i][j]]++;
            pre[t[i][j]]++;
            G[t[i][j]].push_back(i);
        }
    for(int i=1;i<=n;i++)
        dfs(i);
}

D.Feeding Chicken

首先算出lim=cntRKlim=\lfloor\frac{cnt_R}{K}\rfloor即爲每種顏色最低分配的RR的數量,我們可以從上到下SS型貪心塗色。對於前(cntRKlim)×(lim+1)(cnt_R-K*lim)\times(lim+1)RR來說,每lim+1lim+1RR的顏色都是相同的;在這之後,每limlimRR塗一種顏色即可。時間複雜度O(nm)O(nm)

#include<bits/stdc++.h>
using namespace std;
int T,n,m,k;
char a[111][111];
vector<char> c;
int main()
{
    for(char i='a';i<='z';i++)c.push_back(i),c.push_back(i-'a'+'A');
    for(char i='0';i<='9';i++)c.push_back(i);
    scanf("%d",&T);
    while(T--)
    {
        int cnt=1,num=0;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",a[i]+1);
            for(int j=1;j<=m;j++)cnt+=(a[i][j]=='R');
        }
        for(int i=1;i<=n;i++)
            if(i&1)
                for(int j=1;j<=m;j++)
                {
                    if(a[i][j]=='R')num++;
                    a[i][j]=c[num*k/cnt];
                }
            else
                for(int j=m;j>=1;j--)
                {
                    if(a[i][j]=='R')num++;
                    a[i][j]=c[num*k/cnt];
                }
        for(int i=1;i<=n;i++)
            printf("%s\n",a[i]+1);
    }
}

E1&2.Send Boxes to Alice

SiS_i表示所給數列前ii項之和,若使所有盒子裏的數都能被大於11的數kk整除,則kk必是SnS_n的質因子。因此,我們可以預處理出所有可能的素因子kk

對於每一個kk,設ii位置之前都滿足kSnk|S_nSnS_n能被kk整除),則對於第ii個位置來說,若要滿足題目條件,只能將第ii個位置的數減少(從ii向後分)或增加(從ii之後向ii分),對答案的貢獻即爲min(Si%k,kSi%k)min(S_i\%k,k-S_i\%k)。枚舉所有可能的kk併線性時間內處理答案取最小值即可。時間複雜度O(δn)O(\delta n)δ\deltaSnS_n的素因子個數,爲10210^2之內的常數。

#include <bits/stdc++.h>
#define ll long long
#define N 1000010
using namespace std;
int n;
ll a[N],sum[N],tmp,ans=(1LL<<60);
vector<ll> fac;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i],sum[i]=sum[i-1]+a[i];
    tmp=sum[n];
    if(tmp==1)
    {
        cout<<-1;
        return 0;
    }
    for(ll i=2;i*i<=tmp;i++)
        if(tmp%i==0)
        {
            while(tmp%i==0)tmp/=i;
            fac.push_back(i);
        }
    if(tmp>1)fac.push_back(tmp);
    for(auto it:fac)
    {
        ll s=0;
        for(int i=1;i<n;i++)
            s+=min(sum[i]%it,it-sum[i]%it);
        ans=min(ans,s);
    }
    cout<<ans;
}

F.Point Ordering

未完待續


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章