开始: 2022-07-23 19:00:00

2022年7月双周赛2(初级班)

结束: 2022-07-23 21:30:00
当前: 2025-0606-0202 01:20:21  类型:OI 状态:已经结束 

A. 手机

一道比较简单的模拟题,主要考察读题的仔细程度和字符串处理的能力。

首先我们对26个字母打表需要按几次键盘,打表,即建立一个数组专门存储一些数据,如这道题可以这么建立:

int num[26]={1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4};        //26个字母打表需要按几次 

之后整行读入字符串,判断字母和空格即可。

#include<bits/stdc++.h> using namespace std; int ans; string a; int num[26]={1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4}; //26个字母打表需要按几次 int main() { getline(cin,a);//整行读入 for(int i=0;i<a.length();i++) { if(a[i]>='a'&&a[i]<='z') ans+=num[a[i]-'a']; //注意判断一个字符是否是字母的方法 if(a[i]==' ') ans++; //不要写else,因为可能有换行符或其他字符 } printf("%d",ans); return 0; }

B. 三角形

做此题主要需要掌握两点间距离的计算方法,公式已经在题目中给出,注意用double存储即可。

为了方便,这里用函数给出了求两点间距离的公式,然后调用三次函数。

如果有同学没有学到函数,将公式写三遍也可。

#include<bits/stdc++.h>
using namespace std;
double dis(double x1, double y1, double x2, double y2)
{
return sqrt(abs((x1 - x2) * (x1 - x2)) + abs((y1 - y2) * (y1 - y2)));
}
int main()
{
double x1, y1, x2, y2, x3, y3, c;
cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
double dis1 = dis(x1, y1, x2, y2), dis2 = dis(x2, y2, x3, y3), dis3 = dis(x3, y3, x1, y1);
c = dis1 + dis2 + dis3;
printf("%.2f", c);
return 0;
}

C. 集合求和

首先需要明确集合的概念,集合一般被定义为:由一个或多个确定的元素所构成的整体。满足以下特性:

确定性:给定一个集合,任给一个元素,该元素或者属于或者不属于该集合,二者必居其一,不允许有模棱两可的情况出现。

互异性:一个集合中,任何两个元素都认为是不相同的,即每个元素只能出现一次。

无序性:一个集合中,每个元素的地位都是相同的,元素之间是无序的。

然后需要明确子集的概念:设S,T是两个集合,如果S的所有元素都属于T ,即称S是T的子集。空集是T的子集,T也是T的子集。

这道题就算不太明确上述概念,通过样例大家也能大概明确题目意思。这道题看起来很难,但其实可以用数学方法简单地做出来。

举个例子,假设有一个集合[1 2 3 4],子集包括[] [1] [2] [3] [4] [1 2] [1 3] [1 4] [2 3] [2 4] [3 4] [1 2 3] [1 2 4] [1 3 4] [2 3 4] [1 2 3 4],容易发现,其中每个数字出现的次数是相同的,都是8次,即2的3次方,再多举个例子我们很容易发现规律,答案为:元素和*2^(n-1) 。

求2的次方,我们可以用pow函数解决,第一个参数是底数,第二个参数是指数。

同时这道题需要注意,输入的元素个数是不定的,需要用while输入,且需要开long long。

#include<bits/stdc++.h>
using namespace std;
int main()
{
long long sum=0,g=0,a;
while(cin>>a)
{
sum+=a;
g++;
}
long long ans=pow(2,g-1)*sum;
printf("%lld",ans);
return 0;
}

D. 判断子序列

这道题体现了一个算法思想:双指针。

其实这道题解决的方法并不难,分别用两个指针指向两个数组中的元素,依次向后找。

具体而言,假设两个指针分别是i和j,i指向a序列中的元素,j指向b序列中的元素。

如果a[i]==b[j], 那么a[i] 这个数是子序列的一部分,i++,j++,继续往后找。

如果a[i]!=b[j] 那么a[i]这个数所对应的b数组中的元素可能还在j之后,故只让j++。 

找到最后,如果a中每个元素都与b中元素一一对应了,此时i应该等于n,输出yes,否则输出no。

如果不太理解上述过程,可以自己在纸上模拟一下再看代码。

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, m;
int a[N], b[N];
int main()
{
scanf("%d%d", &n, &m);
 for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
 for (int i = 0; i < m; i ++ ) scanf("%d", &b[i]);
 int i = 0, j = 0;
 while (i < n && j < m)
 {
   if (a[i] == b[j]) i ++ ;
   j ++ ;
 }
 if (i == n) printf("Yes");
 else printf("No");
 return 0;
}