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.
[align=center] B - Two Heaps
[/align]
题意:给n个数,要求将这n个数分别分到2个不同的堆,从第一个堆取出一个数ab和第二个堆取出一个数cd组成数abcd,使得这个数不同的个数最多.给出分配方式.
思路:各个数都不相同,则一个一个分配是比较容易的.但若有某个数出现不止一次的则需要平均分配到两个堆.
写的有些繁琐,改进:
1.对于某个交替变换的变量,可用^运算符.
2.上面的t,o分别表示两个堆的不同数的个数,那么可以在输入的时候就判断该数的出现次数,若大于1的则在两个堆中都出现,若为1则只可能在某一个堆中.设出现次数大于1的数的个数有y个,出现次数等于1的有x个.
那么t*o=(y+x/2)*(y+x-x/2);
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)作比较取最大值.
[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个数有关.
题意:给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 Round #197 (Div. 2)
- Codeforces Round #198 (Div. 1)
- Codeforces 405E Codeforces Round #238 (Div. 2)E
- Codeforces 407C Codeforces Round #239 (Div. 1)C
- CodeForces 449A - Jzzhu and Chocolate
- CodeForces 449 B. Jzzhu and Cities
- codeforces 618C. Constellation
- Codeforces Round #349 (Div. 2) - C
- Codeforces Round #361 (Div. 2)
- 7.13Codeforces Round #360 (Div. 2)
- Codeforces Round #363 (Div. 2)
- Codeforces Round #265 (Div. 2)
- Codeforces #310 div2 C. Case of Matryoshkas
- 状态压缩DP codeforces 244 Problem C. The Brand New Function 和 codeforces 165 E. Compatible Numbers
- codeforces 16 Problem E fish
- Codeforces Round332 部分题解
- CodeForces 603A_Alternative Thinking (DP)
- CodeForces 602B_Approximating a Constant Range_DP
- Codeforces round #247 for Div. 2
- Codeforces Round #246 (Div. 2)