Advertisement

上海市计算机学会2022年10月月赛丙组试题

阅读量:

第一题 直角三角形判定

题目描述

给定三个正整数表示三角形的三条边,请判定它是否为直角三角形。

输入格式

第一行:三个整数 a,b 与 c

输出格式

若可以构成一个直角三角形,输出 Right Triangle
否则,输出 No

数据范围

1\leq a, b, c\leq 1000

样例输入1:

3 4 5

样例输出1:

Right Triangle

样例输入2:

3 3 3

样例输出2:

NO

分析

简单的分支结构判断,先将最大值交换到 c 中,再用勾股定理判断就行了。

复制代码
    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
    	int a, b, c;
    	cin >> a >> b >> c;
    	if (a > b) swap(a, b);
    	if (b > c) swap(b, c);
    	if (a * a + b * b == c * c)
    		cout << "Right Triangle" << endl;
    	else
    		cout << "No" << endl;
    	return 0;
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI写代码

第二题 因子分解

题目描述

给定一个正整数 nn,请将它分解为素数的乘积。

例如 60=2\times2\times3\times5

输入格式

单个整数表示 n

输出格式

若干整数表示 n 的素因子,按照从小到大的顺序输出。

数据范围

2\leq n\leq 1,000,000,000

样例输入1:

60

样例输出1:

2 2 3 5

样例输入2:

3

样例输出2:

3

问题分析

  • 考虑枚举 n 的因子,用 n 除它,直到不能整除,这样找到的因子一定是素因子。
复制代码
    for (int i = 2; i <= n; ++i)
    	while (n % i == 0){
    		cout << i << " ";
    		n /= i;
    	}
    
    
      
      
      
      
      
    
    AI写代码

算法是O(n),超时。

  • 结论:整数 n 大于 \sqrt n 的素因子可能有 01个。(反证法容易证明)
    因此,只需要枚举到 \sqrt n,如果最后原数还未变成 1,则该数一定是唯一的大于 \sqrt n 的素因子。时间复杂度:O(\sqrt n)
复制代码
    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
       int n, m;
       cin >> n;
       m = n;
       for (int i = 2; i * i <= n; ++i){
       	while (m % i == 0){
       		cout << i << " ";
       		m /= i;
       	}
       }
       if (m != 1) cout << m << endl;
       return 0;
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI写代码

第三题 算术求值(一)

题目描述

给定一个由正整数、加号、减号构成的表达式,请计算表达式的值。

输入格式

输入一个由 正整数、+、- 构成的表达式

输出格式

单个整数:表示算式的值。

数据范围

数据保证输入的字符串长度不超过 100,000,其中出现的整数不超过 10000。

样例数据:

2+12-5

样例输出:

9

问题分析

简单模拟题

复制代码
    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
    	char op = '+';
    	long long ans = 0, t;
    	while (op != ' '){
    		cin >> t;
    		if (op == '+')
    			ans += t;
    		else
    			ans -= t;
    		op = ' ';
    		cin >> op;
    	}
    	cout << ans << endl;
    	return 0;
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI写代码

第四题 门禁记录

题目描述

小爱得到了某大楼一天内按时间顺序记录的 n 条门禁出入记录,每条记录由两个字符串组成,第一个字符串为出入人员姓名,第二个字符串表示该人员进出状态、为 enterexit 中一项,其中 enter 为进入, exit 为离开。

小爱发现,部分人员的门禁信息存在错误,即某人在没有进入记录时便有了离开记录,或是某人有进入记录但没有离开记录。

已知在第一条记录前及最后一条记录后,大楼内均没有任何人员。请你根据门禁记录,来分析哪些人员的门禁信息存在错误?

输入格式

输入第一行,一个正整数 n
接下来 n 行,每行两个字符串,以空格隔开,其中第 i + 1 行的两字符串分别表示第 i 条记录的人员姓名与出入信息。

输出格式

按字典序输出所有出入信息存在错误的人员姓名,按空格隔开

数据范围

对于30\%的数据,1 \leq n \leq 10
对于60\%的数据,1 \leq n \leq 10^3
对于100\%的数据,1 \leq n \leq 2\times10^4 ,且人员姓名字符串长度不超过10。

样例输入:

5
Xiaoai enter
Bob exit
Xiaoai exit
Alice exit
Alice enter

样例输出:

Alice Bob

说明:

Bob只有exit数据,存在信息缺失
Alice的exit数据前不存在enter,而在最后一条enter后也没有exit,存在信息缺失

问题分析

模拟题。
用map<string, string>标记每个人的状态,如果冲突就存储到set集合中。最后输出set中的名字即可。

复制代码
    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
    	map<string, string> mp;
    	int n;
    	string s, t;
    	set<string> ans;
    	cin >> n;
    	while (n--){
    		cin >> s >> t;
    		if (t == "enter"){
    			if (mp.find(s) != mp.end() && mp[s] == "enter")
    				ans.insert(s);
    			else
    				mp[s] = t;
    		}			
    		else {
    			if (mp.find(s) == mp.end() || mp[s] == "exit"){
    				ans.insert(s);
    			} else {
    				mp[s] = t;
    			}
    		}
    	} 
    	map<string, string>::iterator it;
    	for (it = mp.begin(); it != mp.end(); it++){
    		if (it->second != "exit") ans.insert(it->first);
    	}
    	for (set<string>::iterator it = ans.begin(); it != ans.end(); ++it)
    		cout << *it << " ";
    	cout << endl;
    	return 0;
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI写代码

第五题 组队竞赛

题目描述

n 同学想要参加小爱组建的一支信息学竞赛队伍,每位同学有能力值 a_i 与热情度b_i

小爱认为,如果队伍当中,能力值最大与能力值最小选手之间,能力差值大于给定 X,会导致能力差距过大、不利于团队的学习与凝聚力。因此,请你帮助小爱计算下,如何选择队伍的选手,才能使所有选手的能力差值小于等于 X,且热情度最大。

输入格式

输入第一行,一个正整数 n,表示有 n 位选手
接下来 n 行,每行两个正整数a_i,b_i 表示每位选手的能力值与热情度。
最后一行,一个正整数 X,表示小爱希望的能力差值上限

输出格式

输出一个整数,表示满足条件的情况下,最大热情度的值

数据范围

对于30\%的数据,1 \leq n \leq 100
对于60\%的数据,1 \leq n \leq 10^4
对于100\%的数据,1 \leq n \leq 10^5,1 \leq d \leq 10^9,1 \leq a_i,b_i \leq 10^9

样例输入:

5
10 21
20 34
30 27
40 89
50 54
20

样例输出:

170

说明:

选第3、4、5个选手。
能力值分别为30、40、50,不超过50-30=20给定的能力差值上限20
此时热情度为27+89+54=170

问题分析

求能力值差不超过 x, 最大热情度的和。

  • 枚举最小能力值,O(n)查找大于等于该能力值并且差值不大于X的热情度和,打擂台求最大值。时间复杂度:O(n^2).
  • 按能力值排序,问题变成能力值差不大于 X 的最大热情度区间和。指针 l 指向第一个人,r 向后移动找到能力值差值不大于 X的最远的人,维护区间内热情度的和,得到左端点为 1 的最大区间和。l每次向后移动, r 向后找能力值差值不大于X的最远的人,维护区间热情度和,打擂台求最大值即可。 当 r = n 循环结束,即可找到解。时间复杂度:O(n\log n)
复制代码
    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1E5 + 10;
    
    struct nod{
    	int a, b;
    };
    
    bool cmp(nod p, nod q){
    	return p.a < q.a;
    }
    
    nod c[MAXN];
    int n, x;
    
    int main(){
    	cin >> n;
    	for (int i = 0; i < n; ++i)
    		cin >> c[i].a >> c[i].b;
    	cin >> x;
    	sort(c, c + n, cmp);
    	long long ans = 0, s2 = 0;
    	int l = 0, r = 0;
    	while (r < n){
    		while (r < n && c[r].a - c[l].a <= x){
    			s2 += c[r].b;
    			r++;
    		}
    		ans = max(ans, s2);
    		s2 -= c[l].b;
    		l++;
    	}
    	cout << ans << endl;
    	return 0; 
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI写代码

全部评论 (0)

还没有任何评论哟~