第一题:得分
有2N张扑克牌,每张牌印有一个数字,数字范围[1,2N],且每张牌的数字都不相同。
FJ拿了其中的N张牌,Bessie拿剩下的N张牌,然后他们共进行N轮对打,每一轮对打就是各自出一张牌,数字大的一方获得1分。
已知FJ第i轮出的牌是f[i],Bessie第i轮出的牌是b[i]。
求FJ最后的得分。
【输入格式】
一行,1个整数N。1 <= N <= 50。
第二行,N个整数,第i个整数是f[i]。
第三行,N个整数,第i个整数是b[i]。
【输出格式】
一个正整数。
【输入样例】
2
1 3
4 2
【输出样例】
1
解题思路:使用数组接收输入,然后比较两个数组数据的大小,然后使用标记变量记录结果即可。附代码如下:
#include <bits/stdc++.h>
using namespace std;
int n,f[55],b[55],ans;
int main(){
cin>>n;
for(int i=0;i<n;i++)
cin>>f[i];
for(int i=0;i<n;i++)
cin>>b[i];
for(int i=0;i<n;i++)
if(f[i]>b[i])
ans++;
cout<<ans;
return 0;
}
第二题:单元格
Cat Taro有一个N行和N列的正方形网格。网格的每个单元格都涂成黑色或白色。
Taro想要选择一段连续的单元格,这段单元格必须位于同一列中并且有相同的颜色。
求他可以选择的最大数量的单元格。
【输入格式】
第一行,一个整数N。1 <= N <= 50。
接下来是N行N列的网格。每个各自要么是白色 'W', 要么是黑色 'B’。
【输出格式】
一个整数。
【输入样例】
4
BWBW
BBWB
WWWB
BWWW
【输出样例】
3
解题思路:首先,先分析输入/输出样例,输出样例为3,表示最长的连续同色格子是第三列的3个W。这题考察二维数组的搜索,定义二维字符数组接收输入。这题的关键点是,在使用二重循环搜索二维数组时,需要先改变二维数组的行坐标,再改变二维数组的列坐标(先移动行坐标再移动列坐标)。而在搜索的过程中,需要考虑如果位于两种方格的交界处,则需要将计数器变量重置为1,重新统计结果。附代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,ans;
char a[55][55];
int main(){
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>a[i][j];
for(int j=0;j<n;j++)
{
int t=1;
for(int i=0;i<n-1;i++)
if(a[i][j]==a[i+1][j])
t++;
else
ans=max(t,ans),t=1;//如果出现两种颜色交界,需要重置计数变量
ans=max(t,ans);
}
cout<<ans;
return 0;
}
第三题:字符串排序
给出一个字符串数组String stringList[1..N] ,已知stringList数组里面N个字符串长度都不相同。
到目前为止,奶牛Bessie已经学会了两种排序字符串的方法:
1、它可以按字典顺序对字符串进行排序。例如,"car"<"carriage"<"cats"<"doggies"。
2、它还学会了根据字符串的排序长度升序排列。例如,"car"<"cats"<"doggies"<"carriage"。
Bessie现在想知道stringList是否以这两种方式中的任何一种排序。
如果stringList按字典顺序排序但不根据字符串长度排序,则输出"lexicographically"。
如果stringList根据字符串长度排序但不按字典顺序排序,则输出"lengths"。
如果以两种方式排序,则输出"both"。
否则,输出"none"。
【输入格式】
第一行,一个整数N。1<=N<=50。
接下来有N行,每行一个字符串,第i行字符串是stringList[i],字符串由小写英文字母构成,长度不超过50。
【输出格式】
一个字符串,不用输出双引号。
【输入样例】
3
a
aa
bbb
【输出样例】
both
【输入/输出例子2】 输入: 3 c bb aaa 输出: lengths 【输入/输出例子3】 输入: 2 etdfgfh aio 输出: none
解题思路:题目要求比较用户输入的多个字符串是否已经按照字典序或者字符串长度进行排序,判断后输出对应的单词。最简单的方式是定义两个字符串数组,按用户输入的顺序存储的字符串,然后分别编写两个自定义sort排序函数,排序后与原数组比较,再使用一个标记变量比较得出结果。附代码如下:
#include <bits/stdc++.h>
using namespace std;
int n,flag=3;
string s[55],s2[55];
bool cmp(string a,string b)//按字典序排序
{
return a<b;
}
bool cmp2(string a,string b)//按字符串长度从小到大排序
{
return a.size()<b.size();
}
int main(){
cin>>n;
for(int i=0;i<n;i++)
{
cin>>s[i];
s2[i]=s[i];
}
sort(s,s+n,cmp);
for(int i=0;i<n;i++)//比较是否按字典序排序
if(s[i]!=s2[i])
{
flag-=1;
break;
}
sort(s,s+n,cmp2);
for(int i=0;i<n;i++)//比较是否按字符串长度排序
if(s[i]!=s2[i])
{
flag-=2;
break;
}
if(flag==3)
cout<<"both";
else if(flag==2)
cout<<"lengths";
else if(flag==1)
cout<<"lexicographically";
else
cout<<"none";
return 0;
}
附第二种简化代码写法:
#include<bits/stdc++.h>
using namespace std;
int n,l1,l2;
string a,b;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>b;
if(b<a) l1=1;//标记没有按照字典序排序
if(b.size()<a.size()) l2=1;//标记没有按照字符长度排序
a=b;
}
if(l1==1&&l2==1) cout<<"none";
else
if(l1==0&&l2==0) cout<<"both";
else
if(l1==0) cout<<"lexicographically";
else cout<<"lengths";
return 0;
}
第四题:整除
小为为二年级数学课正在学整数的除法,她在一张白纸上面已经写了N个不同的整数,第i个整数是d[i]。
小为为现在想要在她的白纸上添加一些新整数。她将使用整数除法。在进行整数除法时,我们丢弃结果的小数部分。
在这个问题中,我们将使用“div”来表示整数除法。例如,15 div 5 = 3, 24 div 5 = 4。
她将重复以下过程:
从白纸上选择两个不同的整数A和B,使得A大于B,计算C = A div B, 如果C未在白纸上出现,她将会把C写到白纸上。
一旦无法在白纸上添加新的整数,该过程就会停止。
问最终白纸上有多少个不同的整数。
【输入格式】
第一行,一个整数N。 1 <= N <= 100。
第二行,N个整数,第i个整数是d[i]。1 <= d[i] <= 100,没有相同的d[i]。
【输出格式】
一个整数。
【输入样例】
2
9 2
【输出样例】
3
【样例解释1】 2 4 9 【输入/输出例子2】 输入: 3 6 2 18 输出: 7 【样例解释2】 1 2 3 4 6 9 18
解题思路:分析样例1,题目要求A/B时,A>B,因此只能9/2=4,添加新的数字4;继续9/4=2,4/2=2;运算后无法添加新的数字,结束运算,输出结果3。这题只需要使用一个数组打标记,判断是否出现新的数字即可。附代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,a[105],t;
bool b[105];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i],b[a[i]]=true;//a数组用于存储当前纸上写着的数字,b数组用于标记出现的数字
for(;;)
{
t=0;//用于标记本轮运算是否出现新数字
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i!=j)
{
int t2=max(a[i],a[j])/min(a[i],a[j]);
if(b[t2]==0)
t=1,b[t2]=1,a[++n]=t2;//标记出现新数字,并将新数字存入a数组以及在b数组打标记
}
}
if(t==0) break;
}
cout<<n;
return 0;
}
第五题:VIP客户
商店出售M种不同类型的商品,编号为0至M-1。
现在有一个购物调查,您采访了N个客户,每个客户都对调查做出回应,并列出了他们购买的商品。
对于同类型的商品,每个客户最多只会购买一件。有些客户可能根本不买任何东西。
如果一个客户购买了商店的所有M种不同商品,那么这种客户就是VIP客户。
调查结束后汇总,发现有s[i]人买了第i 种商品。
由于不幸的事故,调查表丢失了,现在不能确定每个客户具体购买了哪些商品。
万幸的是:汇总数据没有丢失,即s数组保留了下来。
根据s数组,那么至少有多少个VIP客户?
【输入格式】
第一行,两个整数N和M。1 <=N, M<=100
第二行,M个整数,第i个整数是s[i]。 0 <= s[i] <= N。
【输出格式】
一个整数。
【输入样例】
5 2
3 3
【输出样例】
1
【输入/输出样例2】
输入:
10 5
9 9 9 9 9
输出:
5
【输入/输出样例3】
输入:
100 1
97
输出:
97
分析样例1,共有五个顾客和两种商品,每种商品有3个顾客买。为了让VIP客户尽可能少,需要让顾客们尽可能不买同一种商品,如下图,此时VIP客户的数量为2。
分析样例2,共有十个顾客和五种商品,每种商品有9个顾客买。为了让VIP客户尽可能少,需要让顾客们尽可能不买同一种商品,如下图,此时VIP客户的数量为5。
解题思路:这题需要贪心算法的思想。为了让VIP客户尽可能少,需要让顾客们尽可能不买同一种商品,
附代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,m,a,s;
int main()
{
cin>>n>>m>>a;
s=a;//s用于记录当前vip客户的数量;s先初始化为购买商品0的顾客数量
for(int i=2;i<=m;i++)
{
cin>>a;
s=s+(a-n);
//a-n先求出本轮最多可以有多少个商品不去购买
//s+(a-n)用s加上a-n是从当前的vip数量将去本轮最多可以不去购买的商品数量
}
if(s>0)//特判
cout<<s;
else
cout<<0;
return 0;
}
第六题:棋盘
Bessie正在学习如何下象棋。棋盘有P行P列。行和列编号都是0至P-1。
我们可以使用其两个坐标值来描述每个单元格:(r,c)。
Bessie最近了解到其中一个棋子:教主。教主每次的移动方式非常特殊。
不妨假设教主当前所在位置是单元格(r,c),则1次移动可到达的所有单元格包括:
1、(r + k,c + k)形式的所有单元格,其中k是正整数。
2、(r + k,c - k)形式的所有单元格,其中k是正整数。
3、(r - k,c + k)形式的所有单元格,其中k是正整数。
4、(r - k,c - k)形式的所有单元格,其中k是正整数。
当然,教主必须始终在棋盘内,不能走到棋盘外面。
现在Bessie拿来了一个空的棋盘,他把一个教主放在格子(r1,c1)。
他现在想要使用尽可能少的移动将其移动到单元格(r2,c2),请输出最小的移动次数。
如果教主不可能到达目标单元格,则返回-1。
【输入格式】
一行,5个整数: P,r1,c1,r2,c2。
【输出格式】
一个整数。
【输入样例】
8 4 6 7 3
【输出样例】
1
【数据范围】
P = 10^9, 0 <= r1,c1,r2,c2 < P。
首先阅读数据范围,发现P的最大值可以是10的9次方,看出即使使用一重循环进行遍历也会超时,因此,立刻就想到了这题是数学知识题,找出对应的规律就可以得出答案。
对样例进行分析,根据样例数形结合绘制一个8*8的棋盘图案进行分析,下图中的绿色格子表示样例中教主棋的初始位置,黄色的格子表示教主至少走一步就可以到达的区域;红色格子表示教主棋至少需要走两步才可以到达的区域,白色的格子表示教主棋子不能到达的区域。由下图可知,教主棋子从(4,6)的位置要到达(7,3)的位置至少需要走一步。
解题思路:结合上图进行分析,这题的输出结果共有四种情况:
第一种情况:目标位置与起始位置相同,则不需要要移动教主棋子就可以到达目标位置,输出0。
第二种情况:教主棋子至少需要走一步就可以到达的位置,输出1。
第三种情况:教主棋子至少需要走两步就可以到达的位置,输出2。
第四种情况:教主棋子无法到达的位置,输出-1。
这题的输出结果共分为四种情况,只需要找出这四种情况的规律既可以得出题目答案。第一种情况,只需要直接判断即可。第二种情况,分别求出目标位置与起始位置的行列坐标偏移的绝对值,如果两个数的结果相等,则该种情况。由于第四种情况比第三种情况好判断,因此先判断第四种情况,最后剩下的情况一定是第三种情况。第三种情况,分别求出目标位置与起始位置偏移位置绝对值得奇偶性是否相同,如果奇偶性不同,则目标位置不可达。
附代码如下:
#include <bits/stdc++.h>
using namespace std;
int P,c1,r1,c2,r2;
int main(){
cin>>P>>c1>>r1>>c2>>r2;
int t1=abs(c1-c2),t2=abs(r1-r2);
if(c1==c2&&r1==r2)//目标位置等于起始位置
cout<<0;
else if(t1==t2)//走一步可达的位置
cout<<1;
else if(t1%2!=t2%2)//不可达的位置
cout<<-1;
else//至少走两步才可达的位置
cout<<2;
return 0;
}