您的位置:首页 > 其它

Codeforces Round #205 (Div. 2)

2016-07-22 08:09 423 查看
A -Domino

题意:给n个分数,x为分子,y为分母,问经过最少几次分子分母交换,得到分子之和和分母之和都为偶数。

思路:奇数+奇数=偶数,偶数+偶数=偶数,奇数+偶数=奇数。题目x,y范围也就1-6,自己模拟一下也ok.答案只有3种:

1,0,-1.因为只有奇偶两种情况,假设存在多个奇数,每次交换改变奇数个数,奇数个奇数之和为奇数,偶数个奇数之和为偶数.所以答案最大只能为1.

1.Σx,Σy都为偶数,答案为0.

2.Σx,Σy一奇一偶的情况,答案为-1,

3.Σx,Σy都为奇数,那么就要判断是否分子分母为一奇一偶,若不是,则交换无意义,答案为-1.,反之,答案为1.
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,x,y,flag=0,sumup=0,sumlow=0;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&x,&y);
sumup+=x;
sumlow+=y;
if(x%2&&y%2==0)flag=1;
if(x%2==0&&y%2)flag=1;
}
if((sumup%2&&sumlow%2==0)||(sumup%2==0&&sumlow%2))
printf("-1\n");
else if((sumup%2==0&&sumlow%2==0))printf("0\n");
else{
if(flag)printf("1\n");
else printf("-1\n");
}

}


[align=center]  B - Two Heaps
[/align]
题意:给n个数,要求将这n个数分别分到2个不同的堆,从第一个堆取出一个数ab和第二个堆取出一个数cd组成数abcd,使得这个数不同的个数最多.给出分配方式.

思路:各个数都不相同,则一个一个分配是比较容易的.但若有某个数出现不止一次的则需要平均分配到两个堆.
#include<bits/stdc++.h>
using namespace std;
struct node{
int b,id;
}num[205];
int ans[205],v[205];
bool cmp(node a,node b){
return a.b>b.b;
}
int main(){
int n,last,o,t;
scanf("%d",&n);
memset(num,0,sizeof(num));
for(int i=1;i<=2*n;i++){
scanf("%d",&num[i].b);
num[i].id=i;
}
sort(num+1,num+2*n+1,cmp);
last=2,t=o=0;
memset(v,0,sizeof(v));
for(int i=1;i<=2*n;i++){
if(num[i].b==num[i+1].b){
if(!v[num[i].b]){
if(last==2){
ans[num[i].id]=1;
ans[num[i+1].id]=2;
o++,t++;
last=2;
}
else{
ans[num[i].id]=2;
ans[num[i+1].id]=1;
o++,t++;
last=1;
}
v[num[i].b]=v[num[i+1].b]=1;
}
else{
if(last==2){
ans[num[i+1].id]=1,last=1;
}
else ans[num[i+1].id]=2,last=2;
}
}
}
for(int i=1;i<=2*n;i++){
if(!v[num[i].b]){
if(last==2){
ans[num[i].id]=1;
o++;
last=1;
}
else{
ans[num[i].id]=2;
t++;
last=2;
}
}
}
printf("%d\n",t*o);
printf("%d",ans[1]);
for(int i=2;i<=2*n;i++){
printf(" %d",ans[i]);
}
printf("\n");
}


写的有些繁琐,改进:

1.对于某个交替变换的变量,可用^运算符.

2.上面的t,o分别表示两个堆的不同数的个数,那么可以在输入的时候就判断该数的出现次数,若大于1的则在两个堆中都出现,若为1则只可能在某一个堆中.设出现次数大于1的数的个数有y个,出现次数等于1的有x个.

那么t*o=(y+x/2)*(y+x-x/2);
#include<bits/stdc++.h>
using namespace std;
int ans[205],v[205],a[205];
int main(){
int n,x=0,y=0;
scanf("%d",&n);
memset(v,0,sizeof(v));
for(int i=0;i<2*n;i++){
scanf("%d",a+i);
v[a[i]]++;
}
for(int i=10;i<=99;i++){
if(v[i]>1)x++;
if(v[i]==1) y++;
}
int z=(x+y),last=0;
printf("%d\n",(y/2+x)*(y-y/2+x));
for(int i=0;i<2*n;i++){
if(v[a[i]]==1){
ans[i]=last;
last^=1;
}
}
for(int i=10;i<=99;i++){
if(v[i]>1){
for(int j=0;j<2*n;j++){
if(a[j]==i){
ans[j]=last;
last^=1;
}
}
}
}
for(int i=0;i<2*n;i++){
printf("%d ",ans[i]+1);
}
}

C -Find
Maximum

题意:给长度为n的数组a,长度为n的01字符串,m=

,

,求

.f(x)的最大值.

思路:按照题目给的字符串的意思,倒置的二进制,00001=2^4,11110=1+2+2^2+2^3=2^4-1.我们先预处理数组sum[i]表示i之前的数组a的和.将字符串最后一个1开始往前循环,ans=max(ans,sum[i-1]),最后将ans和f(m)作比较取最大值.
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
int a[MAX],sum[MAX];
char str[MAX];
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",a+i);
}
scanf("%s",str);
sum[0]=a[0];
for(int i=1;i<n;i++){
sum[i]=sum[i-1]+a[i];
}
int j=n-1;
while(str[j]=='0'){
j--;
}
int orignal=0,ans=0;
for(int i=j;i>=0;i--){
if(str[i]=='1'){
ans=max(ans,orignal+sum[i-1]);
orignal+=a[i];
}
}
printf("%d\n",max(orignal,ans));
}

[align=center]D - Queue
[/align]
题意:给一个MF的字符串,问至少需要几步才能把F全部移到左边,M全部移到右边.F可以移到左边为M,即MF->FM.

思路:MF->FM只需1步,MMFF->FFMM需要3步,原因是第二个F的前面是个F,需要第一个F先移动一步变得MFMF,然后第二个F才能移动.说明移动的步数除了和在F左边的M的个数有关,还和第一个F身后相邻的F个数有关.
#include<bits/stdc++.h>
using namespace std;
char str[1000005];
int main(){
scanf("%s",str);
int j=0,m=0,ans=0;
while(str[j]=='F')j++;
for(int i=j;i<strlen(str);i++){
if(str[i]=='M')m++;
else ans=max(ans+1,m);
}
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces