广西大学东信杯第四届程序设计竞赛(同步赛)部分题解

本文主要是介绍广西大学东信杯第四届程序设计竞赛(同步赛)部分题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

赛题链接:牛客(NC)广西大学第四届程序设计竞赛(同步赛) 点击传送

借鉴了mrgg等诸位大佬的代码

第一次写题解,希望大佬勿喷,时间有限,错误难以避免,希望各位大佬指正

A题 Antinomy与比赛的含金量(签到题)

 签到题,给n个比赛,每个比赛有三个参数a,b,c如果a,b大于90,c大于60,输出A+,否则输出E+。

#include <iostream>
using namespace std;
int main()
{int T;scanf("%d",&T);while(T--){int a,b,c;scanf("%d%d%d",&a,&b,&c);printf("%s\n",(a>90&&b>90&&c>60)?"A+":"E+");}return 0;
}

B题 Antinomy与取模(数论)

数论入门题

两个知识点:GCD(最大公约数)、LCM(最小公倍数)

1.最大公约数GCD

整数a和b的最大公约数记为gcd(a,b)。在编程时有两种做法

(1)经典的欧几里得算法,用辗转相除法求最大公约数,模板如下:

int gcd(int a,int b){

return b==0? a:gcd(a%b);

}

时间复杂度差不多是O(log2n)的,非常快。

(2)或者直接用c++的内置函数求GCD

包含在头文件algorithm下

std::__gcd(a,b)

2.最小公倍数LCM

整数a和b的最小公倍数记为lcm(a,b),模板如下:

Int lcm(int a,int b){

Return a/gcd(a,b)*b;

}

由题意可知yi是a和b的最小公倍数的整数倍。且yi介于l和r之间。所以我可以先求得a,b的最小公倍数,记为c。由于l<=yi<=r,所以我们可以推得 l/c<=yi/c<=r/c(c=0的情况也满足)

所以让倍数i从l/c遍历到r/c,一旦i*c介于l和r之间,即可输出并跳出循环。如果遍历完还没有输出即不存在答案,输出-1。

#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;
}int main() {int t;cin >> t;ll a, b, l, r;while (t--) {int flag = 0;cin >> a >> b >> l >> r;ll c = lcm(a, b);for (int i = l/ c; i <= r / c; i++) {if (l <= i*c && i*c <= r) {cout << i*c << endl;flag = 1;break;}  }if(flag==0)cout << "-1" << endl;}return 0;
}

C题 Antinomy与清理魔法(排序题)

sort函数用于C++中,对给定区间所有元素进行排序,默认为升序,也可进行降序排序。sort函数进行排序的时间复杂度为n*log2n,比冒泡之类的排序算法效率要高,sort函数包含在头文件为#include<algorithm>的c++标准库中。

由于对选择的下标没有要求,为了便于筛选,我们可以通过排序获得一个升序的整齐序列。(这样可以使得任意两个数值相近的数在空间上靠在一起)我们利用贪心的思想,遍历数组,如果前一个数减去后一个数的差值大于k,那么,输出NO并跳出循环,最后如果都满足便输出YES。

#include<bits/stdc++.h>
#define ll long long
using namespace std;const int N=5007;inline  ll read()//快读板子
{ll x=0,ch=getchar(),j=1;while(!isdigit(ch)){if(ch=='-') j=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*j;
}ll n,k;
ll a[N];int main()
{n=read(),k=read();for(int i=1;i<=n;i++){a[i]=read();}  sort(a+1,a+1+n);for(int i=2;i<=n;i++){if(a[i]-a[i-1]>k){cout<<"NO";return 0;}}cout<<"YES";
}

D题 Antinomy学内存对齐

 

根据内存对齐的部分规则以及备注可知,默认的对齐数是4,也就是说int、long、float这些4字节和double、long long、long double这些8字节的成员可以留在最后输出(因为它们的字节数都是4的倍数)。所以只需要考虑char、bool、short这三个成员的顺序情况

即优先级:char>bool>short

如代码所示,结构体node类型数组s[maxn]中每个元素都存储一个字符串string pa和一个优先级p。每次输入一行字符串,通过判断这行字符串的首字母’c’ ‘b’ ‘s’来对这行字符串赋予优先级:即’c’为首的字符串优先级为1,最高,依次类推。

贴个代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int maxn = 1e6 + 10;struct node {string pa;int p;
}s[maxn];
int t = 0;
string st, ed;bool cmp(node a, node b) {return a.p < b.p;
}int main() {getline(cin, st);while (getline(cin, s[++t].pa)) {string str = s[t].pa;int len = str.size();if (str == "};")break;if (str[0] == 'c')s[t].p = 1;else if (str[0] == 'b')s[t].p = 2;else if (str[0] == 's')s[t].p = 3;else s[t].p = 4;}sort(s + 1, s + t, cmp);cout << st;for (int i = 0; i < t; i++) {cout << s[i].pa<<endl;}cout << "};";return 0;
}      

E题 Antinomy慢慢点技能树(01背包)

仔细读题,每个技能最多只能点一次,也就是点或者不点两种情况。可以对应到01背包问题上来

关于01背包问题,可以参考这篇博客:动态规划之01背包问题 - kkbill - 博客园

对于每一个精确到小数点后4位的浮点数,由于不能按int类型直接处理,我们可以将它扩大1w倍,这样它就可以被当作int类型来处理了

But

很多同学发现,为什么扩大1w倍后仍然不能ac呢?这里涉及到一个小小的知识点,也就是说会出现下面这种情况:

 具体解释可以参考:组成原理|为什么计算机中0.3 + 0.6 等于 0.899999999...? - fishers - 博客园

也就是说我们如果想要使得答案准确,需要给原来的数上加上一点数,使得它可以进位,从而不会发生如上图所示的情况。

解决这些问题后,答案就显然易见了:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e5+7;
double x[maxn];
long long w[maxn];
long long v[maxn];
ll dp[maxn];
int main(){int t = 1;while(t--) {ll n ,k;cin >> n;k = 10000;for(int i = 1; i <= n ; i++) {scanf("%lf%lld",&x[i],&v[i]);w[i] = (x[i]+0.000001)*10000;for(int j = k;j>=w[i];j--) {dp[j] = max(dp[j],dp[j - w[i]] + v[i]);}}     cout<<dp[k]<<"\n";}
}
本题解用到了滚动数组:
在处理dp[][]状态数组的时候有一个小技巧:把它变成一维的dp[],以节省空间。观察二维表dp[][]可以发现,每一行是从上面一行算出来的,只跟上面一行有关系,跟更前面的行没有关系。那么用新的一行覆盖原来的一行就可以了。
滚动数组板子:(hdu2602)
int dp[T];
int ans(){memset(dp,0,sizeof(dp));for(int i=1;i<=N;i++)for(int j=V;j>=bone[i].vol;j--)dp[j]=max(dp[j],dp[j-bone[i].vol]+bone[i].val);return dp[V];
}

F题 Antinomy与金手指(kmp解法)

仔细读题,本题可以这样理解:

第一次输入一个字符串str

第二次输入一个字符串pattern

当时做题时,我想到了一个经典问题:石子合并问题

其中处理一段循环石子堆时,它使用了将石子堆重复两遍的方法来进行合并

所以利用这种思想,我们来处理这道题:

如str=abcde pattern=cdeab的情况时,我们可以修改str=abcdeabcde,然后判断str是否存在一段pattern序列,如果存在即满足条件。

当然可以选择暴力搜索,就是算法复杂度会很大(因为n<=2e6)

这里我选择使用kmp算法,当然大佬可以考虑更优的算法AC自动机、后缀树等,这里不做过多讲解。

Kmp算法可以参考下列这篇博客:

(原创)详解KMP算法 - 孤~影 - 博客园

贴个代码:

#include<iostream>
using namespace std;
const int MAXN = 400005;
//char str[MAXN], pattern[MAXN];
string str, pattern;
int Next[MAXN];
int cnt=0;
void getfail(string p, int plen) {Next[0] = 0; Next[1] = 0;for (int i = 1; i < plen; i++) {int j = Next[i];while (j && p[i] != p[j]) j = Next[j];Next[i + 1] = (p[i] == p[j]) ? j + 1 : 0;}
}
void kmp(string s, string p) {int last = -1;int slen = s.length(), plen = p.length();getfail(p, plen);int j = 0;for (int i = 0; i < slen; i++) {while (j && s[i] != p[j])j = Next[j];if (s[i] == p[j]) j++;if (j == plen) {if (i - last >= plen) {cnt++;last = i;}}}}
int main() {int n;cin >> n;cin >> str;str += str;cin >> pattern;kmp(str, pattern);if (cnt != 0) cout << "wow";else cout << "TAT";return 0;
}

 以上就是我对这次比赛部门题目的理解。由于太菜了,只能解释这点题目。不正确的地方希望有大佬能帮忙指正,拜托了拜托了。

这篇关于广西大学东信杯第四届程序设计竞赛(同步赛)部分题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/166321

相关文章

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Linux搭建Mysql主从同步的教程

《Linux搭建Mysql主从同步的教程》:本文主要介绍Linux搭建Mysql主从同步的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux搭建mysql主从同步1.启动mysql服务2.修改Mysql主库配置文件/etc/my.cnf3.重启主库my

Java中将异步调用转为同步的五种实现方法

《Java中将异步调用转为同步的五种实现方法》本文介绍了将异步调用转为同步阻塞模式的五种方法:wait/notify、ReentrantLock+Condition、Future、CountDownL... 目录异步与同步的核心区别方法一:使用wait/notify + synchronized代码示例关键

详谈redis跟数据库的数据同步问题

《详谈redis跟数据库的数据同步问题》文章讨论了在Redis和数据库数据一致性问题上的解决方案,主要比较了先更新Redis缓存再更新数据库和先更新数据库再更新Redis缓存两种方案,文章指出,删除R... 目录一、Redis 数据库数据一致性的解决方案1.1、更新Redis缓存、删除Redis缓存的区别二

Nacos集群数据同步方式

《Nacos集群数据同步方式》文章主要介绍了Nacos集群中服务注册信息的同步机制,涉及到负责节点和非负责节点之间的数据同步过程,以及DistroProtocol协议在同步中的应用... 目录引言负责节点(发起同步)DistroProtocolDistroSyncChangeTask获取同步数据getDis

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &