G - 0011
NBUT - 1626
这道题考察的是字符数组、字符串方面的知识。我在字符数组、字符串上的知识比较薄弱,一开始就卡在了要如何输入这串字符上,没想到直接开一个字符数组,用cin输入就可以了。
在思维方面上,这题主要考验我们找特点、总结,找规律的能力。
根据题意所述,我们可以发现,一个合法的字符串要有相同数量的0和1,而且0在1前。可以概括为:
前面有几个连续的0,后面就有几个连续的1。
后面有几个连续的1,前面就有几个连续的0。
发现了这一点后就很简单了,下面上代码。
#include<iostream>
#include<cstring>
using namespace std;
char s[1006];//开比1000大一点的字符数组
int l;
int main()
{
int n;
cin>>n;
while(n--)
{
l=0;
int q=1;
cin>>s;
for(int i=0;i<=strlen(s)-1;i++)
{
if(s[i]=='1') l--;//字符型用得是''
else if(s[i]=='0') l++;
if(l<0) q=0;//在过程中后面连续的1多于前面连续的0 不合法
}
if(l>0) q=0;//前面连续的0多于后面连续的1 不合法
if(q==0) printf("NO
");
else printf("YES
");
}
return 0;
}
E - 由你来决定怎么颁奖
CodeForces - 1264A
这道题目的文字量也很大,而且题目还在最后还多加了一个条件,容易忽略:让奖牌的数量在满足其他条件的基础上最大。
i.e.是“换句话说、也就是说”的意思。补充:e.g.=for example。
题目大意是:在金牌数量小于银牌和铜牌的数量,并且获奖人数不能超过总人数的一半的基础上,让你去分配奖牌,使奖牌的数量最大。如果分配不了,则输出"0 0 0"。
这种题目就按题目的意思模拟一遍就ok了。
至于如何实现请见代码,不多bb了。
#include<iostream> using namespace std; int p[400010]; int main() { int t; scanf("%d",&t); while(t--) { int n; int g=0,s=0,br=0; scanf("%d",&n); int mid=n/2; for(int i=1;i<=n;i++) { scanf("%d",&p[i]); } if(n<10) { printf("0 0 0 "); continue; } while(p[mid]==p[mid+1]) mid--; int a=1,b=1; for(int i=1;i<=mid-1;i++) { if(p[i]!=p[i+1]) { if(a==1) a=0; else if(b==1) { if(s>g) b=0; else s++; } } if(p[i]==p[i+1]) { if(a==1) g++; else if(b==1) s++; } } g++;s++;br=mid-g-s; if(g<s&&g<br) printf("%d %d %d ",g,s,br); else printf("0 0 0 "); } }
F - XorXor
NBUT - 1615
这道题只要你知识点都掌握了就不难。
知识点:异或运算——分别比较两个数的二进制的各个位数是否相同,若不同,则此位为1,若相同则此位为0。在C语言里," ^ "即异或运算符,可以直接使用。
容易发现:一个相同的数异或偶数次等于0,异或奇数次等于它本身。
Tip:一般先递增,达到一个最大值后,再递减的类似二项式展开式的数列各项都满足类似i*(n-i+1)的式子。
#include<iostream> using namespace std; int a[100010]; int b[100010]; int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=1;i<=n;i++) { int f=i*(n-i+1); if(f%2==0) b[i]=0; else if(f%2==1) b[i]=a[i]; } int ans=0; for(int i=1;i<=n;i++) { ans^=b[i]; } printf("%d ",ans); } }
D - Eat Candies
CodeForces - 1263A
这道题是道找数学本质题,也可以说是思维转换题。
题目的大意是给你三种不同的糖果,且三种不同的糖果的数量不确定。让你输入每种糖果的数量,问每天吃两种不同的糖果、每种一颗,最多可以吃几天。
那么,我们可以将这个问题转换成数学模型:给你三个数,使它们相互抵消,抵消至最小的绝对值要抵消几次(每次抵消1)。
于是,我们可以想到让最大值-第二大和最小值。但是又有一个问题,那就是这个值可能是负的,绝对值不小。这就说明,最小值中的部分数浪费了。
这三个数是可以拆开的。那么我们将浪费的数分成两份,一份用来帮助第二大值抵消最大值,一份可以抵消剩下的第二大的值。这样最后的值不是0就是1,即绝对值最小了。
注意这里的最大、第二大、最小都是不严格的。我们求的是这个过程中相互抵消的次数。
看清了问题的本质,代码实现就很容易了,下面上代码。
#include<iostream> #include<algorithm> using namespace std; int main() { int t; int s[4]; scanf("%d",&t); while(t--) { for(int i=1;i<=3;i++)
{ scanf("%d",&s[i]); }
sort(s+1,s+4); int sum=s[1]+s[2]; if(sum>s[3]) printf("%d ",s[3]+(sum-s[3])/2); else printf("%d ",sum); } return 0; }
H - Perfect String
CodeForces - 1265A
这道题的文字量比较大,一开始看上去,会觉得好像很难的样子。但是,只要你读懂了题目的意思,其实并不难。考验的是你的读题、概括题意的能力。
题目的大意就是给你a、b、c三个元素,让你将任意一串含有‘?’的字符串改成任意相邻元素不相同的字符串,如果改不了,则输出"-1"。
那么只要从头开始判断当前元素是否和后一个元素是否相同,若相同,则输出"-1",结束判断。如果遇到"?",则将它换成一个与前后均不相同的元素。若在此过程中,没有中断判断,则输出改好的字符串。
#include<cstdio> #include<cstring> using namespace std; char str[100005]; int main() { int t; scanf("%d",&t); while(t--) { int q=1; scanf("%s",str);//这里不需要加&符号 int len=strlen(str);//注意函数不能写在for循环的括号里,这样会导致超时的 for(int i=0;i<=len-1;i++) { if(str[i]==str[i+1]&&str[i]!='?') {printf("-1 ");q=0;break;} else if(str[i]=='?') { if(str[i-1]!='a'&&str[i+1]!='a') str[i]='a'; else if(str[i-1]!='b'&&str[i+1]!='b') str[i]='b'; else if(str[i-1]!='c'&&str[i+1]!='c') str[i]='c'; } } if(q==1) printf("%s ",str); }
return 0;
}