京龙杯周赛Round1题解

京龙杯周赛Round1题解

比赛链接:http://10.11.50.84:8080/contest/24

A题

题目大意

给出一个n,求1到n所有数的和。
难度:easy签到题

解题思路

这个题没有卡O(n),所以暴力遍历也能水过。正解直接套等差数列求和公式n*(n+1)/2即可水过。本题注意开long long

#include<bits/stdc++.h>
using namespace std;
int main()
{
	long long int n;
	cin>>n;
	cout<<n*(n+1)/2;
	return 0;
 }

B题

题目大意

题意在题目中介绍的很清晰,注意k=0时也可以前进一格
难度:easy

解题思路

由于数据范围很小,贪心、dp、搜索都可以解决,但是贪心、dp做法时间更快。贪心做法就是每次找最大前进步数,如果有障碍就最大步数–,若一直无法前进,就直接break,输出0。

#include<iostream>
#include<cstdio>
using namespace std;
int n,d;
int main()
{
 	cin>>n>>d;
 	string s;
 	cin>>s;
 	int len = s.length();
 	int now = 0;
 	int pre = 0;
 	bool f = 1;
 	int t = 0;
 	while(now != n-1){
     	now+=d+1;
  	while(now >= len || s[now] == 'X') now--; 
  	if(now == pre) {
  	 f  = 0;
  	 break;
 	 }
  	t++;
  	pre = now;
 	}
 	if(!f){
 	 cout<<0;
 	}else{
 	 cout<<t;
 	}
  
 return 0;
}

然后这个题,我们可以线性DP解决,dp[i]代表到此位置的最小跳跃步数,我们可以得出状态转移方程dp[i]=dp[j]+1,j代表能到达i点的编号,对于j,我们直接枚举遍历即可。

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxN = 111111;
int a[100];
int main(){
	string s;
	
	int n,d;
	cin>>n>>d;
	cin>>s;
	for(int i=1;i<n;i++)a[i] = maxN;
	for(int i=1;i<n;i++){
		for(int j=i-d-1;j<i;j++){
			if(j>=0&&s[i]=='.'&&s[j]=='.'){
				a[i] = min(a[i],a[j]+1);
			}
		}
	}
//	for(int i=0;i<n;i++)cout<<a[i]<<" ";
	if(a[n-1]==maxN)cout<<0;
	else cout<<a[n-1];
	return 0;
}

C题

题目大意

给你一个序列,序列每个数都小于等于长度n,问这个序列是不是长度为n的一个全排列
难度:easy

解题思路

由于全排列的性质,每个数字最多出现一次,所以若有一个数字出现超过1次,那么这个序列肯定不是全排列的一个排列,所以我们开一个数组标记判断即可

#include<iostream>
#include<cstdio>
using namespace std;
bool ton[10085];
int main()
{
 int n;
 cin>>n;
 bool f = 1;
 for(int i = 1;i<=n;i++){
  int x;
  cin>>x;
  if(ton[x] == 1){
   f = 0;
  }else{
   ton[x] = 1;
  }
 }
 if(f){
  cout<<"Yes";
 }else{
  cout<<"No";
 }
 return 0;
}

D题

题目大意

主要就是题面意思,根据题目给出代码,写出自己的优化代码算法
难度:Medium+easy

解题思路

看到大的数据范围,我们就要想到打表找规律或者是数学公式推导,这个题我们需要打表找规律,不难发现每当maxgcd变化时,其对应的值为斐波那契数列的一项,所以根据斐波那契递推公式f[n]=f[n-1]+f[n-2],求解即可

#include<iostream>
using namespace std;
typedef long long ll;
ll x = 1,y = 1,z,n;
int main(){
		x = 1;y = 1;
		int cnt = 2;
		cin>>n;
		while(x<=n){
			z = x;
			x = y + x;
			y = z;
			cnt++;
		}
		cout<<cnt-1;
	return 0;
}
打表数据:
1 2
2 3
3 4
4 4
5 5
6 5
7 5
8 6
9 6
10 6
11 6
12 6
13 7
14 7
15 7
16 7
17 7
18 7
19 7
20 7
21 8
22 8
23 8
24 8
25 8
26 8
27 8
28 8
29 8
30 8
31 8
32 8
33 8
34 9
35 9
36 9
37 9
38 9
39 9
1 2 3 5 8 13 21 34

E题

题目大意

还是题面本身意思,求数组的一段区间和。
难度:Medium+easy

解题思路

这个题首先我们需要对前缀和有所了解,如果我们对每次询问都用循环求解,显而易见O(n2)会超时,所以我们需要更高级的处理方法降低时间复杂度。这时候我们需要引入前缀和,即预先对数列的1~i处理出前缀和,我们定义sum[i]为数组a[1]…a[i]的和,这样处理之后,我们就可以在每次询问过程中做到O(1)处理答案了,对于l到r的区间和即为sum[r]-sum[l]+a[l]的值,注意本题数据量较大,若用cin和cout会超时,所以选用scanf,printf输入输出

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e6+6;
long long int sum[maxn];
long long int a[maxn];
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		sum[i]=sum[i-1]+a[i];
	}
	int q;
	scanf("%d",&q);
	for(int i=1;i<=q;i++)
	{
		int l,r;
		scanf("%d%d",&l,&r);
		printf("%lld\n",sum[r]-sum[l]+a[l]);
	}
	return 0;
}

F题

题目大意

见题面,题面介绍的很清楚了

解题思路

直接根据题意模拟即可,如果是偶数,那么拆分之后两部分也一定是偶数所以就是yes。如果是奇数,肯定分不出两个偶数,所以即为no。注意我们要加一个特判,在偶数情况下,如果是2的情况也是no,因为2只能分为1和1,两个都为奇数,不符合yes的题意。
代码:

#include<iostream>
using namespace std;
typedef long long ll;
int main(){
	int a;
	cin>>a;
	if(a%2)cout<<"No";
	else if(a<4)cout<<"No";
	else cout<<"Yes";
	return 0;
}

比赛过程总结

1.printf与scanf的规范写法

longlong要用%lld
int用%d

2.数组大小

开数组的大小要比规定大小大一些

3.开longlong

看到大于1e9的数据一定要开long long

4.边界数据

在一些小的数据或者是边界情况要加入特判

活动总结

这次题目我们基本面向的是社团新生和刚入门的同学,所以题目难度都较低。每个题都有一定启发性,无论是细节处理还是新算法的引入,都可以让刚入门的同学学到许多新知识。
附难度顺序:
A F C
B
E D

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值