开始: 2022-03-05 19:00:00

2022年3月双周赛(高级班)

结束: 2022-03-05 21:30:00
当前: 2025-0505-3131 13:53:19  类型:OI 状态:已经结束 

最长连号

 

许多同学没拿满分的原因在于数组没开够,这道题数据范围明确说是不超过100000,然而很多同学只开到了10000,并且要注意因为数组比较大,只能用全局变量,使用局部变量会爆栈。或者这道题其实并不需要数组,用临时变量保存当前的数和前一个数即可。

示范代码采用数组写法,思路较简单,若a[i]=a[i-1]+1则sum++,若不等于则sum=1,若当前sum>ans即更新答案。

 

代码如下:

#include<bits/stdc++.h>

using namespace std;

int n,a[100010];

int sum=1,ans=1;

int main()

{

cin>>n;

for(int i=1;i<=n;i++) cin>>a[i];

for(int i=2;i<=n;i++)

{

if(a[i]==a[i-1]+1) sum++;

else sum=1;

if(sum>ans) ans=sum;

}

cout<<ans;

return 0;

}

 

谁拿了最多奖学金

 

这是一道较简单的模拟题,只要认真读题,理清逻辑,题目其实非常简单,主要考察读题的认真程度、对结构体及其排序的掌握。注意最后排序的时候若获得的奖学金相同,需要根据输入顺序排序。

 

代码如下:

 

#include<bits/stdc++.h>

using namespace std;

int all,n;

struct node

{

string s;

int sum,num;

}a[110];

bool cmp(node x,node y)

{

if(x.sum==y.sum) return x.num<y.num;

return x.sum>y.sum;

}

int main()

{

cin>>n;

for(int i=1;i<=n;i++)

{

cin>>a[i].s;

a[i].num=i;

int x,y,z;

char q[2],w[2];

cin>>x>>y>>q>>w>>z;

if(x>80&&z>=1) a[i].sum+=8000;

if(x>85&&y>80) a[i].sum+=4000;

if(x>90) a[i].sum+=2000;

if(x>85&&w[0]=='Y') a[i].sum+=1000;

if(y>80&&q[0]=='Y') a[i].sum+=850;

all+=a[i].sum;

}

sort(a+1,a+1+n,cmp);

cout<<a[1].s<<endl<<a[1].sum<<endl<<all;

return 0;

}

 

前缀和

题库原题,主要思想正如题目名字,鉴于已有视频讲解,不再细说。需要注意的是许多同学失分在使用了cin/cout导致超时,对于输入输出数据比较多的题目尽量使用scanf/printf。

部分同学忘了前缀和的写法便直接放弃这道题,但这道题暴力方法十分显然,并且能得到绝大部分分数,在比赛时不应该放弃能得到的分。

 

代码如下:

 

#include<bits/stdc++.h>

using namespace std;

const int N=100010;

int a[N],sum[N];

int L[N],R[N];

int main()

{

    int n,m,x;

    cin>>n>>m;

    for(int i=1;i<=n;i++)

    {

        scanf("%d", &x);

        sum[i]=x+sum[i-1];

    }

    for(int i=0;i<m;i++)

    {        

        scanf("%d%d", &L[i], &R[i]);        

    }

    for(int i=0; i<m; i++){

     printf("%d\n", sum[R[i]]-sum[L[i]-1]);

}

    return 0;

}

 

集合求和

 

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

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

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

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

然后需要明确子集的概念:设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) 。

严谨的数学推导如下:

 

代码如下(来自唐珞珈同学):

 

#include<bits/stdc++.h>

using namespace std;

 

int main() {

long long sum=0,g=0,a;

while(cin>>a){

sum+=a;

g++;

}

long long zjh=pow(2,g-1)*sum;

printf("%lld",zjh);

    return 0;

}