Codeforces Round #601 (Div. 2)

Codeforces Round #601 (Div. 2)

A. Changing Volume

题意:有T组数据,每组数据给两个数ab,每次可以对a进行(-5-2-1+1+2+5)操作中的一种,问从a转换为b最少需要多少次。

思路:贪心,对a和b的差取绝对值,先尽可能多的选操作5,再尽可能多的选操作2,最后再选操作1 .

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int total,a,b;
    int num[3]={5,2,1};
    cin>>total;
    while(total--){
        cin>>a>>b;
        long long cha=abs(a-b);
        int ans=0;
        if(cha>0){
            for(int i=0;i<3;i++){
                ans+=cha/num[i];
                cha%=num[i];
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
View Code

B. Fridge Lockers

题目数据范围被修改了,现在改为了m≤n,就很好写了

题意:给n个点,让建m条边,要求每个点至少有2个临边,建边的费用为边的两个顶点之和,问能否建出该图,如果能输出最小建造费用,否则输出-1.

思路:形成环即可,m<n和n=2时不满足要求。(这是原题目:m>n时的思路和证明:传送

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int total,n,m,get_num;
    cin>>total;
    while(total--){
        cin>>n>>m;
        int ans=0;
        for(int i=1;i<=n;i++){
            cin>>get_num;
            ans+=get_num;
        }
        if(n==2 || m<n){
            cout<<-1<<endl;
        }else{
            ans*=2;
            cout<<ans<<endl;
            for(int i=1;i<=n;i++){
                int j=(i+1>n?1:i+1);
                cout<<i<<" "<<j<<endl;
            }
        }
    }
    return 0;
}
View Code

C. League of Leesins

题意:有一串序列,比如[1,4,2,3,5],给出它每三个数字的排序{[1,4,2],[4,2,3],[2,3,5]},现在将其打乱,大分组顺序和小分内组顺序都可能会变化如变为:

{[2,4,3],[1,2,4],[5,3,2]},现在给出被打乱后的序列,请输出它对应的任意一组可能的顺序序列

思路:开始和结尾的数只会出现一次,找到开始和结尾,然后可以确定开始的那一组,之后每两个数都能确定第三个数,用map做一下即可。

(我是unordered_map套了vector,初始化每组数中每两个数做一次key,第三个数作为值塞入对应key的vector中,后面判断总的大数组中相邻的数对应key的vector的size为2,间隔数对应key的vector的size为1)

#include<bits/stdc++.h>
using namespace std;
int book[100005];
vector<int>ans;
unordered_map<long long,vector<int> >tree;
vector<int>null_vec;
struct node{
    int a,b,c;
}que[100005];
void solve(int a,int b,int c){
    long long xiao=1LL*min(a,b);
    long long da=1LL*max(a,b);
    long long key=xiao*1000000+da;
    if(tree.find(key)==tree.end()){
        tree[key]=null_vec;
        tree[key].push_back(c);
    }else{
        tree[key].push_back(c);
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n,a,b,c;
    cin>>n;
    memset(book,0,sizeof(book));
    for(int i=1;i<=n-2;i++){
        cin>>a>>b>>c;
        que[i].a=a;que[i].b=b;que[i].c=c;
        solve(a,b,c);
        solve(a,c,b);
        solve(b,c,a);
        book[a]++;
        book[b]++;
        book[c]++;
    }
    int start,k1,k2,end_p,gg;
    for(int i=1;i<=n;i++){
        if(book[i]==1){
            start=i;
            gg=i+1;
            break;
        }
    }
    for(int i=gg;i<=n;i++){
        if(book[i]==1){
            end_p=i;
            break;
        }
    }
    for(int i=1;i<=n;i++){
        if(que[i].a==start){
            k1=min(que[i].b,que[i].c);
            k2=max(que[i].b,que[i].c);
            break;
        }else if(que[i].b==start){
            k1=min(que[i].a,que[i].c);
            k2=max(que[i].a,que[i].c);
            break;
        }else if(que[i].c==start){
            k1=min(que[i].a,que[i].b);
            k2=max(que[i].a,que[i].b);
            break;
        }
    }
    ans.push_back(start);
    while(ans.size()+3<n){
        long long key=1LL*k1*1000000+1LL*k2;
        int num1=tree[key][0];
        int num2=tree[key][1];
        int type=0;
        int kk1,kk2;
        if(num1==start){
            kk1=min(k2,num2);
            kk2=max(k2,num2);
            type=1;
        }else if(num2==start){
            kk1=min(k2,num1);
            kk2=max(k2,num1);
            type=2;
        }
        long long nk=1LL*kk1*1000000+1LL*kk2;
        if(tree[nk].size()==1){
            swap(k1,k2);
            if(type==1){
                kk1=min(k2,num2);
                kk2=max(k2,num2);
            }else if(type==2){
                kk1=min(k2,num1);
                kk2=max(k2,num1);
            }
        }
        ans.push_back(k1);
        start=k1;k1=kk1;k2=kk2;
    }
    long long gk1=min(start,k1);
    long long gk2=max(start,k1);
    long long ggkey=gk1*1000000+gk2;
    if(tree[ggkey].size()==1){
        swap(k1,k2);
    }
    for(int i=0;i<ans.size();i++){
        cout<<ans[i]<<" ";
    }
    cout<<k1<<" "<<k2<<" "<<end_p<<endl;
    return 0;
}
View Code

D. Feeding Chicken

题意:r×c大小的农场养k只鸡,有些单位格上有米粒,现在给鸡分配空间,要求:每个鸡至少得到一个单位格,每只鸡的活动区域要4联通,自己的区域不能分开,获得米粒最多的鸡和获得米粒最少的鸡的米粒差尽可能小。

思路:S型给鸡分配场地即可,扫描得总米粒数为x,有x%k只鸡吃x/k+1粒米,有k-x%k只鸡吃x/k粒米,(我不知道整除时怎么放入总情况所以单独写了一遍整除时的,所以代码比较长(裂开))。

#include<bits/stdc++.h>
using namespace std;
char ditu[105][105];
char ans[105][105];
int t,r,c,k;
int every_l,every_h,cont_h,cont_l;
string biao="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

void solve0(){
    int ct_h=0,ct_l=0;
    for(int i=0;i<r;i++){
        if(i%2==0){
            for(int j=0;j<c;j++){
                if(ditu[i][j]=='R'){
                    ans[i][j]=biao[ct_h];
                    ct_h++;
                }else{
                    if(ct_l<cont_l){
                        ans[i][j]=biao[cont_h+ct_l];
                        ct_l++;
                    }else{
                        if(i==0){
                            ans[i][j]=ans[i][j-1];
                        }else
                            ans[i][j]=ans[i-1][j];
                    }
                }
            }
        }else{
            for(int j=c-1;j>=0;j--){
                if(ditu[i][j]=='R'){
                    ans[i][j]=biao[ct_h];
                    ct_h++;
                }else{
                    if(ct_l<cont_l){
                        ans[i][j]=biao[cont_h+ct_l];
                        ct_l++;
                    }else{
                        ans[i][j]=ans[i-1][j];
                    }
                }
            }
        }

    }
    return;
}

void solve(){
    int ct_h=0,ct_l=0,cont_mi=0;
    for(int i=0;i<r;i++){
        if(i%2==0){
            for(int j=0;j<c;j++){
                if(ditu[i][j]=='R'){
                    cont_mi++;
                    if(ct_h==cont_h){//is small
                        if(cont_mi>every_l){
                            cont_mi=1;
                            ct_l++;
                            ans[i][j]=biao[cont_h+ct_l];
                        }else{
                            ans[i][j]=biao[cont_h+ct_l];
                        }
                    }else{//is big
                        if(cont_mi<every_h){
                            ans[i][j]=biao[ct_h];
                        }else{
                            cont_mi=0;
                            ans[i][j]=biao[ct_h];
                            ct_h++;
                        }
                    }
                }else{
                    if(ct_h==cont_h){
                        if(cont_l==0) ans[i][j]=biao[cont_h-1];
                        else ans[i][j]=biao[cont_h+ct_l];
                    }else{
                        ans[i][j]=biao[ct_h];
                    }
                }
            }
        }else{
            for(int j=c-1;j>=0;j--){
                if(ditu[i][j]=='R'){
                    cont_mi++;
                    if(ct_h==cont_h){//is small
                        if(cont_mi>every_l){
                            cont_mi=1;
                            ct_l++;
                            ans[i][j]=biao[cont_h+ct_l];
                        }else{
                            ans[i][j]=biao[cont_h+ct_l];
                        }
                    }else{//is big
                        if(cont_mi<every_h){
                            ans[i][j]=biao[ct_h];
                        }else{
                            cont_mi=0;
                            ans[i][j]=biao[ct_h];
                            ct_h++;
                        }
                    }
                }else{
                    if(ct_h==cont_h){
                        if(cont_l==0) ans[i][j]=biao[cont_h-1];
                        else ans[i][j]=biao[cont_h+ct_l];
                    }else{
                        ans[i][j]=biao[ct_h];
                    }
                }
            }
        }
    }
    return;
}

int main()
{
    scanf("%d",&t);
    while(t--){
        int rice=0;
        scanf("%d %d %d\n",&r,&c,&k);
        for(int i=0;i<r;i++){
            scanf("%s",ditu[i]);
            for(int j=0;j<c;j++){
                if(ditu[i][j]=='R') rice++;
            }
        }
        every_l=rice/k,every_h=every_l+1,cont_h=rice%k,cont_l=k-cont_h;
        if(every_l==0) solve0();
        else solve();
        for(int i=0;i<r;i++){
            for(int j=0;j<c;j++){
                printf("%c",ans[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}
View Code

E1. Send Boxes to Alice (Easy Version)

题意:一行有n个盒子,每个盒子有1个或没有巧克力,每次操作可以将第i个盒子中的一个巧克力放入第i-1或者第i+1个盒子中(盒子存在),问最少操作几次,最后所有有巧克力的盒子中的巧克力数能被k整除

思路:先分解质因数,因为是easy版本所以对于每个质因子pr,每pr个有巧克力的盒子分为一组,枚举放入每一个盒子的操作数取和的最小值即可,优化一下前缀后缀暴力就能过。

#include<bits/stdc++.h>
using namespace std;
vector<int>que;

long long solve(int pr)
{
    long long sum=0;//will return the value;
    for(int st=0;st<que.size();st+=pr){
        long long ans=0;
        for(int i=1;i<pr;i++){
            ans+=que[st+i]-que[st];
        }
        long long l=0,r=pr-1,zuo=0,you=ans;
        for(int i=1;i<pr;i++){
            l+=1;
            zuo+=l*(que[st+i]-que[st+i-1]);
            you-=r*(que[st+i]-que[st+i-1]);
            r--;
            ans=min(ans,zuo+you);
        }
        sum+=ans;
    }
    return sum;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n,get_num;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>get_num;
        if(get_num>0){
            que.push_back(i);
        }
    }
    if(que.size()<=1){
        cout<<-1<<endl;
    }else{
        long long ans=10000000000000000;

        vector<int>prime;
        int size_p=que.size();
        prime.push_back(size_p);
        for(int pr=2;pr*pr<=size_p;pr++){
            bool flag=false;
            while(size_p%pr==0){
                flag=true;
                size_p/=pr;
            }
            if(flag)prime.push_back(pr);
        }
        if(size_p>1)prime.push_back(size_p);

        for(int i=0;i<prime.size();i++){
            ans=min(ans,solve(prime[i]));
        }
        cout<<ans<<endl;
    }
    return 0;
}
View Code

E2. Send Boxes to Alice (Hard Version)

题意:如E1,只是每个盒子中巧克力个数Ai范围改为[0,1e6]

思路:还是先分解质因数,对于一个数Ai,假设当前的质因数为pr,这个位置要满足能被k整除,有两个可能,要么是它往后面搬运pr%k石子,要么是后面往它搬运k-pr%k个石子。

对于每一个Ai满足后,因为只会对下一个位置产生影响,所以下一个位置Ai+1算上Ai产生的影响,之后又是一个新的子问题。

最后的答案为:对于每一个质因数pr,对每个位置i求min(pre[i],pr-pre[i])的和,最有取所有和种的最小值作为答案。

#include<bits/stdc++.h>
using namespace std;
int num[1000005];

long long solve(long long pr,int n){
    long long pre=0,ans=0;
    for(int i=1;i<=n;i++){
        pre=(pre+num[i])%pr;
        ans+=min(pre,pr-pre);
    }
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n;
    long long sum=0,ans=1e18;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>num[i];
        sum+=num[i];
    }
    if(sum<=1){
        cout<<-1<<endl;
        return 0;
    }
    for(long long pr=2;pr*pr<=sum;pr++){
        bool flag=false;
        while(sum%pr==0){
            flag=true;
            sum/=pr;
        }
        if(flag) ans=min(solve(pr,n),ans);
    }
    if(sum>1) ans=min(solve(sum,n),ans);
    cout<<ans<<endl;
    return 0;
}
View Code

F. Point Ordering

题意:是一个交互题,挺有意思。在笛卡尔坐标系中有一个n个点形成的凸包,你有2种询问,第一种:询问任意三个点形成的三角形的面积。

第二种:询问任意3个点形成的2个向量的叉积的符号。要求在3n次询问内得知凸包点的顺序,从1开始逆时针输出。

思路:首先考虑叉积,2个向量a×b,若为正则b在a的左侧,若为负则b在a的右侧。第一步:以任意一对点为基准(这里采用1-2),用第二种查询得到1-2与所有不同于1-2的1-X的叉积符号,分为左右两组。第二步:对于每一侧,使用第一种查询查X、1、2,三个点形成的三角形面积的两倍,从而可以知道这一侧每个点距离1-2向量的距离,取最远的那个点记为点Y(如有多个任取其中一个即可)。第三步:再用第二种查询得到这一侧所有的1-X与1-Y的叉积符号,再根据其距离,得到这一侧的所有点的顺序。另一侧同理。

#include<bits/stdc++.h>
using namespace std;
 
double query1(int i,int j,int k){
    double answer;
    cout<<1<<" "<<i<<" "<<j<<" "<<k<<endl;
    cin>>answer;
    return answer;
}
 
int query2(int i,int j,int k){
    int answer;
    cout<<2<<" "<<i<<" "<<j<<" "<<k<<endl;
    cin>>answer;
    return answer;
}
struct node{
    int loc;
    double dis;
}now;
vector<node>loc_left,loc_right;
vector<int>ans;
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    for(int i=3;i<=n;i++){
        if(query2(1,2,i)==1){
            now.loc=i;
            loc_left.push_back(now);
        }else{
            now.loc=i;
            loc_right.push_back(now);
        }
    }
    for(int i=0;i<loc_left.size();i++){
        loc_left[i].dis=query1(1,2,loc_left[i].loc);
    }
    for(int i=0;i<loc_right.size();i++){
        loc_right[i].dis=query1(1,2,loc_right[i].loc);
    }
    sort(loc_left.begin(),loc_left.end(),[](const node &a,const node &b){return a.dis>b.dis;});
    sort(loc_right.begin(),loc_right.end(),[](const node &a,const node &b){return a.dis>b.dis;});
 
    ans.push_back(0);ans.push_back(1);
 
    vector<int>loc_right_l,loc_right_r;
    if(!loc_right.empty()){
        int right_max=loc_right[0].loc;
        for(int i=0;i<loc_right.size();i++){
            if(right_max==loc_right[i].loc) continue;
            if(query2(1,right_max,loc_right[i].loc)==1){
                loc_right_l.push_back(loc_right[i].loc);
            }else{
                loc_right_r.push_back(loc_right[i].loc);
            }
        }
        if(!loc_right_r.empty()){
            for(int i=loc_right_r.size()-1;i>=0;i--){
                ans.push_back(loc_right_r[i]);
            }
        }
        ans.push_back(right_max);
        for(int i=0;i<loc_right_l.size();i++){
            ans.push_back(loc_right_l[i]);
        }
    }
 
    ans.push_back(2);
 
    vector<int>loc_left_l,loc_left_r;
    if(!loc_left.empty()){
        int left_max=loc_left[0].loc;
        for(int i=0;i<loc_left.size();i++){
            if(left_max==loc_left[i].loc) continue;
            if(query2(1,left_max,loc_left[i].loc)==1){
                loc_left_l.push_back(loc_left[i].loc);
            }else{
                loc_left_r.push_back(loc_left[i].loc);
            }
        }
        if(!loc_left_r.empty()){
            for(int i=loc_left_r.size()-1;i>=0;i--){
                ans.push_back(loc_left_r[i]);
            }
        }
        ans.push_back(left_max);
        for(int i=0;i<loc_left_l.size();i++){
            ans.push_back(loc_left_l[i]);
        }
    }
 
    for(int i=0;i<ans.size();i++){
        cout<<ans[i]<<" ";
    }
    cout<<endl;
 
    return 0;
}
View Code

这期题还是蛮有意思的~( 逃ε=ε=ε=┏(゜ロ゜;)┛

 

posted @ 2019-11-21 13:37  blacktion  阅读(350)  评论(0编辑  收藏  举报