2019ACM集训队选拔训练赛-第一轮

本文介绍了2019年ACM集训队选拔训练赛的第一轮情况,涉及多个题目,如A题计算排名,B题寻找最简单题目,C题统计鞍点,D题比较次方,E题求最小价值,F题判断平方数,G题解决树舞问题。题目主要通过数学方法和逻辑推理解决,部分涉及算法优化。

第一场训练赛,打之前去交大历险记玩了一圈,在罚时上有点多,但结果还可以(除了C题完全理解错了题意没有做出来以外),整体上难度不是很大没有用什么算法,大部分通过暴力以及一些数学方法就可以解决
在这里插入图片描述

A算算排名第几

描述

在某次ACM比赛中,一共有8道题,分别是A, B, C… H题。题目难度随机分布,最终成绩与AC数目和时间都有关系,具体的排名计算规则如下:若两人AC题目个数不同,则AC题目数多的人排名更靠前;若两人AC题目一样多,则罚时少的人排名更靠前。罚时为:从比赛开始计时,在所有AC的题目中,第一次AC的时间(分钟)+20(分钟)×该题错误提交的次数(编译错误"Compile Error" 不算罚时)。

如:某人在比赛开始 12分时A题 “Compile Error” 24分时A题 “Wrong Answer” 36分时A题"Accepted" 48分时B题"Time Limit Exceeded" 60分时E题"Accepted" 72分钟时B题 “Accepted” 84分时F题"Wrong Answer" 96分时F题"Wrong Answer" 108分时F题"Wrong Answer"。则此人AC题目数量为3题, 总罚时为 20+36+20+60+72=208分

输入

多组测试数据,第一行一个整数T(1<=T<=100),表示包含t组测试数据

每组测试数据第一行包含一个整数n(1<=n<=1000),表示n条提交记录

接下来n行,每行包含一个整数t(0<=t<=300)表示提交时间,一个字符 ch(‘A’ <= ch <= ‘H’)表示提交题号 和一个字符串 str 表示某次提交结果。"Accepted"表示该题正确通过(即AC); "Wrong Answer"表示该题答案错误; "Time Limit Exceeded"表示程序运行时间超出规定时间; "Runtime Error"表示程序运行时发生错误,可能是数组访问越界,除零错误,栈溢出等; “Compile Error” 表示程序编译没有通过; “Memory Limit Exceeded” 表示程序使用内存过多。在错误提交之中,只有 "Compile Error"不计入罚时
输出

每组数据输出一行,包含两个整数a, b 表示AC题目数量和总罚时

比较水的A题,输出包括两个一个AC的题目数量一个是罚时,只需要统计一下Accepted的次数,并记录一下出错的次数,在AC的时候增加一下罚时,不过要注意在评测机不能用gets输入,可以用string头文件里的getline (cin,str);输入


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;

int T,n,sum = 0,pp = 0; 
int a[100];
string str;

int main() {
	cin>>T;
	while(T--) {
		cin>>n;			
		memset(a,0,sizeof(a));
		sum = 0, pp = 0;
		for(int i = 1; i <= n; i++) {
			int time;
			char ch;
			scanf("%d %c",&time,&ch);
			getline (cin,str);
			if(str[1] == 'A') {
				sum++;
				pp += time + a[ch - 'A' + 1] * 20;
			}
			else if(str[1] == 'C') continue;
			else a[ch - 'A' + 1]++; 
		}
		cout<<sum<<' '<<pp<<endl;
	}
	return 0;
} 

B做题有顺序

描述

在某次ACM比赛中,一共有8道题,分别是A, B, C… H题。题目难度随机分布,最终成绩与AC数目和时间都有关系,所以先做简单的题目便成了很多人的选择。为了方便起见,我们认为某题被AC的人数越多,则该题越简单。现给出n条提交记录,试找出最简单的题。

输入

多组测试数据,第一行一个整数t(1<=t<=100),表示包含t组测试数据

每组测试数据第一行包含一个整数n(1<=n<=1000),表示n条提交记录

接下来n行,每行包含一个字符 ch(‘A’ <= ch <= ‘H’) 和一个字符串 str 表示某次提交信息。ch表示此次提交题目题号,str表示提交结果:"Accepted"表示该题正确通过(即AC); "Wrong Answer"表示该题答案错误; "Time Limit Exceeded"表示程序运行时间超出规定时间; "Runtime Error"表示程序运行时发生错误,可能是数组访问越界,除零错误,栈溢出等; “Compile Error” 表示程序编译没有通过; “Memory Limit Exceeded” 表示程序使用内存过多

输出

每组数据输出一行,包含一个字符表示八道题中最简单的题。若多题一样简单,则输出那个最小的题号。
同样水的B题,AC越多,题越简单。统计每个题AC的次数就知道哪个最简单

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;

int T,n;
int a[100];
char p;
string str;


int main() {
	cin>>T;
	while(T--) {
		cin>>n;
		memset(a,0,sizeof(a));
		for(int i = 1; i <= n; i++) {
			cin>>p;
			getline (cin,str);
			if(str[1] == 'A') {
				a[p - 'A' + 1]++;
			}
		}
		int maxx = 0,tot = 1; 
		for(int i = 1; i <= 8; i++) {
			if(a[i] > maxx) {
				maxx = a[i];
				tot = i;
			}
		} 
		char tt = (char)tot + 'A' - 1;
		cout<<tt<<endl; 
	}
	return 0;
} 

C Gao Math

在这里插入图片描述
让我自闭的一道题,原因是完全没有看懂题目的意思,我垃圾的英语水平再一次拖累了我
其实很简单,就是统计有i个鞍点的矩阵数,最后求和。在求和时就会发现,其实结果就是矩阵的所有情况!!!!/喷血

#include<iostream>
#include<cstdio>
using namespace std;

const int mod = 1000000007;
int T,n,m,k;
long long sum;

int main() {
	cin>>T;
	while(T--) {
		cin>>n>>m>>k;
		sum = 1;
		for(int i = 1; i <= m * n; i++) {
			sum = (sum * k) % mod;
		}
		cout<<sum<<endl;
	}
	return 0;
} 

D Comparison

在这里插入图片描述

比较x的y次方和y的x次方的大小,考虑到时间限制以及数据的范围,不能暴力求两数的值,可以通过两边取对数然后比较,可以直接用math库中的log直接比较

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

int a,b;

int main() {
	while(scanf("%d",&a) != EOF) {
		scanf("%d",&b);
		if((double)a * log(b) > (double)b * log(a)) cout<<'<'<<endl;
		else if((double)a * log(b) < (double)b * log(a)) cout<<'>'<<endl;
		else cout<<'='<<endl;
	}
	return 0;
}

E Message

在这里插入图片描述

大体意思是有几个单词的价值可以共享,求一个最小的价值,所以可以对可以共享的价值取min,更新每个单词的价值,然后根据最后信息的内容求一个min值
最开始一直在最后找每个单词价值时一直超时,用map来存一下来减少运行时间

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<map> 
using namespace std; 

const int maxn = 100000 + 100;
int n,k,m;
long long sum = 0;
int val[maxn];
string ch[maxn],p;	
map<string,int> q;

int main() {
	cin>>n>>k>>m;
	for(int i = 1; i <= n; i++)	cin>>ch[i];
	for(int i = 1; i <= n; i++)	cin>>val[i];
	for(int i = 1; i <= k; i++) {
		int t, vis[maxn];
		cin>>t;
		if(t == 1) {
			cin>>t;
			continue;
		}
		int minn = 1e9 + 10;
		for(int j = 1; j <= t; j++)	{
			cin>>vis[j];
			minn = min(val[vis[j]],minn); 
		}
		for(int j = 1; j <= t; j++)	val[vis[j]] = minn; 
	}
	for(int i = 1; i <= n; i++) q[ch[i]] = val[i];
	for(int i = 1; i <= m; i++) {
		cin>>p;
		sum += (long long)q[p];
	}
	cout<<sum<<endl;
	return 0;
} 

F Square

在这里插入图片描述
题意对一个数字,去掉几位数之后,剩下的数是否是一个平方数
首先用map把所有小于2e9的平方数存下来,然后通过暴力的方法将所有情况枚举出来,看是否存在平方数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;

char a[100];
int vis[100];
int l;
map<int,int>q;

int dfs(int x, int p, long long sum) {
	if(p == 1) {
		if(q[sum] == 1) {
			return 1;
		}
		return 0;
	}
	if(x > l) return 0;
	for(int i = x + 1; i <= l; i++) {
		if(dfs(i,p-1,sum * 10 + (long long)vis[i])) return 1;
	}
	return 0;
} 

int init() {
	int i = 1;
	while(i <= 44721) {
		q[i * i] = 1;
		i++;
	}
}

int main() {
	init();
	while(scanf("%s",a) != EOF) {
		l = strlen(a);
		for(int i = 1; i <= l; i++) {
			vis[i] = a[i-1] - '0';
		}
		int pp = 0;
		for(int i = l; i >= 1; i--) {
			for(int j = 1; j <= l; j++) {
				if(vis[j] == 0) continue;
				if(dfs(j,i,vis[j])) pp = 1;
				if(pp) break;
			}
			if(pp) {
				cout<<l-i<<endl;
				break;
			} 
		}
		if(!pp) cout<<"-1"<<endl;
	} 
	return 0;
}

G Tree Dance

在这里插入图片描述

emmm 怎么说这个题,在无疑之中做了出来
首先可以发现对于每两个可以相互跳的点,可以来回跳4次,而且只在这两个点相互跳时最优(不要问我为什么我也不知道)
所以只要能够统计所有可以跳的点之间的倍数之和,乘一个4倍就可以了

#include<iostream>
#include<cstdio>
using namespace std;

int T; 
int n;
int a;

int main() {
	cin>>T;
	while(T--) {
		cin>>n;
		a = 0;
		for(int i = 2; i <= n; i++) {
			for(int j = 2; j <= n; j++) {
				if(i * j <= n) a+=j;
				else break;
			}
		}
		cout<<a * 4<<endl;
	}
} 
间复杂度(渐近间复杂度的严格定义,NP问题,间复杂度的分析方法,主定理)   排序算法(平方排序算法的应用,Shell排序,快速排序,归并排序,间复杂度下界,三种线性间排  序,外部排序)   数论(整除,集合论,关系,素数,进位制,辗转相除,扩展的辗转相除,同余运算,解线性同余方程,中国剩余定理) 指针(链表,搜索判重,邻接表,开散列,二叉树的表示,多叉树的表示) 按位运算(and,or,xor,shl,shr,一些应用) 图论(图论模型的建立,平面图,欧拉公式与五色定理,求强连通分量,求割点和桥,欧拉回路,AOV问题,AOE问题,最小生成树的三种算法,最短路的三种算法,标号法,差分约束系统,验证二分图,Konig定理,匈牙利算法,KM算法,稳定婚姻系统,最大流算法,最小割最大流定理,最小费用最大流算法) 计算几何(平面解几及其应用,向量,点积及其应用,叉积及其应用,半平面相交,求点集的凸包,最近点对问题,凸多边形的交,离散化与扫描) 数据结构(广度优先搜索,验证括号匹配,表达式计算,递归的编译,Hash表,分段Hash,并查集,Tarjan算法,二叉堆,左偏树,二斜堆,二项堆,二叉查找树,红黑树,AVL平衡树,Treap,Splay,静态二叉查找树,2-d树,线段树,二维线段树,矩形树,Trie树,块状链表) 组合数学(排列与组合,鸽笼原理,容斥原理,递推,Fibonacci数列,Catalan数列,Stirling数,差分序列,生成函数,置换,Polya原理) 概率论(简单概率,条件概率,Bayes定理,期望值) 矩阵(矩阵的概念和运算,二分求解线性递推方程,多米诺骨牌棋盘覆盖方案数,高斯消元) 字符串处理(KMP,后缀树,有限状态自动机,Huffman编码,简单密码学) 动态规划(单调队列,凸完全单调性,树型动规,多叉转二叉,状态压缩类动规,四边形不等式) 博奕论(Nim取子游戏,博弈树,Shannon开关游戏) 搜索(A*,ID,IDA*,随机调整,遗传算法)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值