Codeforces Round #608 题解
A题
本题只需要对e,f进行大小比较,决定先买哪个即可,因为jacket对于每类都需要一个,所以以jacket为指标。
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; typedef long long ll; const int N=10010; int main(){ int a,b,c,d,e,f; cin>>a>>b>>c>>d>>e>>f; int s1=min(b,c); if(e>f){ int sum=0; if(a>d){ sum=d*e; } else { sum=a*e+min(d-a,s1)*f; } cout<<sum<<endl; } else{ int sum=0; if(s1>d){ sum=d*f; } else{ sum=s1*f+min(a,d-s1)*e; } cout<<sum<<endl; } }
B题
根据对题目性质的研究,可以看出以下几点
1.变成全黑和全白都可以,所以做两遍判断。
2.考虑变白算法,可以先把两两相邻的黑色全部变白记录,这样剩下的黑色如果是奇数个,则变白不行,进行变黑,如果变黑也不行,那么输出-1
3.对于第一步后剩下的,直接从头开始翻转,必定可以做完。
4.注意特判初始全黑和全白情况。
学习点:一定要牢记特殊情况的判断。
更新:写复杂了,用异或直接判断即可
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; typedef long long ll; const int N=10010; int pos[N]; int main(){ int n; cin>>n; string s; cin>>s; s=" "+s; string b=s; int cnt=0; int i; int s1=0,s2=0; for(i=1;i<=s.size();i++){ if(s[i]=='W') s1++; } if(s1==n||s1==0){ cout<<0<<endl; return 0; } for(i=2;i<=s.size();i++){ if(s[i]=='W'&&s[i-1]=='W'){ pos[cnt++]=i-1; s[i]=s[i-1]='B'; } } int sum=0; for(i=1;i<=s.size();i++){ if(s[i]=='W') sum++; } if(sum%2){ s=b; int cnt=0; int i; for(i=2;i<=s.size();i++){ if(s[i]=='B'&&s[i-1]=='B'){ pos[cnt++]=i-1; s[i]=s[i-1]='W'; } } int sum=0; for(i=1;i<=s.size();i++){ if(s[i]=='B') sum++; } if(sum%2){ cout<<-1<<endl; } else{ for(i=1;i<s.size();i++){ if(s[i]=='B'){ pos[cnt++]=i; s[i]='W'; s[i+1]=s[i+1]=='W'?'B':'W'; } } if(cnt>3*n){ cout<<-1<<endl; return 0; } cout<<cnt<<endl; for(i=0;i<cnt-1;i++){ cout<<pos[i]<<" "; } cout<<pos[i]<<endl; } return 0; } else{ for(i=1;i<s.size();i++){ if(s[i]=='W'){ pos[cnt++]=i; s[i]='B'; s[i+1]=s[i+1]=='B'?'W':'B'; } } if(cnt>3*n){ cout<<-1<<endl; return 0; } cout<<cnt<<endl; for(i=0;i<cnt-1;i++){ cout<<pos[i]<<" "; } cout<<pos[i]<<endl; } }
C题
本题是一道思维题,我刚开始是考虑到,因为是最短路径,所以只要在(xi,sx)-(yi,sy)之间出现的点进行储存计算,后来发现数据范围很大,没有办法开这么大的数组,所以想到一定有简便方法
题目要求任意答案,我们知道所有最短路径都必须经过离学校长度为1的点,因此设计变量abcd如果x<sx,a++,x>sx,b++,y<sy,c++,y>sy,d++,这样比较四个的最大值,找到最大的把摊位设到学校旁边的位置
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; typedef long long ll; const int N=10010; int pos[N]; int l,r,u,d; int main(){ int n; cin>>n; int sx,sy; cin>>sx>>sy; int i; for(i=1;i<=n;i++){ int x,y; cin>>x>>y; if(x<sx) l++; if(x>sx) r++; if(y>sy) u++; if(y<sy) d++; } int mx=0; mx=max(max(l,r),max(u,d)); if(mx==l) sx-=1; else if(mx==r) sx+=1; else if(mx==u) sy+=1; else sy-=1; cout<<mx<<endl; cout<<sx<<" "<<sy<<endl; }
E题
本题于EOJ 1月月赛相同,我是根据别人算法看出规律。
/* 二分判y是否可行,judge函数里: 找规律可以发现: y是奇数时 第0层:y 第一层:2y,2y+1 第二层:4y,4y+1,4y+2,4y+3 第三层:8y,8y+1,8y+2,8y+3,8y+4,8y+5,8y+6,8y+7 ... 第k层:[2^k*y,2^k*y+2^k-1] y是偶数时 第0层:y,y+1 第一层:2y,2y+1,2y+2,2y+3 第二层:4y,4y+1,4y+2,4y+3,4y+4,4y+5,4y+6,4y+7 第三层:8y,8y+1,8y+2,8y+3,8y+4,8y+5,8y+6,8y+7,8y+8,8y+9,8y+10,8y+11,8y+12,8y+13,8y+14,8y+15 ... 第k层:[2^k*y,2^k*y+2^(k+1)-1] 然后统计一下即可 特别注意,对起点是奇数偶数两种情况要特别注意一下,分开来进行二分 */ #include<bits/stdc++.h> using namespace std; #define ll long long ll n,K; ll Pow(ll a,ll b){ ll res=1; while(b){ if(b%2)res=res*a; b>>=1;a=a*a; } return res; } ll judge(ll y){ ll sum=0,k=0; if(y%2==0){//偶数 while(Pow(2,k)*y+Pow(2,k+1)-1<=n){ sum+=Pow(2,k+1); k++; } sum+=max(0ll,n-Pow(2,k)*y+1); } else { while(Pow(2,k)*y+Pow(2,k)-1<=n){ sum+=Pow(2,k); k++; } sum+=max(0ll,n-Pow(2,k)*y+1); } if(sum>=K)return 1; return 0; } int main(){ cin>>n>>K; ll L=0,R=(n-1)/2,mid,ans1=1; while(L<=R){ mid=L+R>>1; if(judge(mid*2+1)) ans1=mid*2+1,L=mid+1; else R=mid-1; } L=1,R=n/2; ll ans2=1; while(L<=R){ mid=L+R>>1; if(judge(mid*2)) ans2=mid*2,L=mid+1; else R=mid-1; } cout<<max(ans1,ans2)<<'\n'; }
没有人不辛苦,只有人不喊疼