Advertisement

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

阅读量:

上海市计算机学会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

分析

\bullet 勾股定理直接判断三个数是否满足直角三角形三边条件即可

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

因子分解

题目描述

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

例如 60=2\times2\times3\times5

输入格式

单个整数表示 n

输出格式

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

数据范围
2\leq n\leq 1,000,000,000

样例数据

输入:

60

输出:

2 2 3 5

输入:

3

输出:

3

分析

\bullet 依次枚举n 的因子直到相同为止最后输出n

代码

复制代码
    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
    	int n;
    	cin >> n;
    	for(int i = 2; i <= n; ++i)
    		while(n != i){
       			if(n % i == 0){
    				cout << i << " ";	
    				n /= i;
    			}	
    	    else  break;
    		} 
    cout << n << endl;
    	return 0; 
    }

算式求值(一)

题目描述

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

输入格式

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

输出格式

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

数据范围

数据保证

输入的字符串长度不超过 100000
其中出现的整数不超过 10000

样例数据

输入:
2+12-5
输出:
9

分析

\bullet 和一年普及组T2相似

\bullet while(cin) 读入每次读入一个符号和一个数字判断加减

代码

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

门禁记录

题目描述

小爱得到了某大楼一天内按时间顺序记录的nn条门禁出入记录,每条记录由两个字符串组成,第一个字符串为出入人员姓名,第二个字符串表示该人员进出状态、为 enter 或 exit 中一项,其中 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,存在信息缺失

分析

\bullet map映射每个人名进出次数,如果进入就加一,离开就减一

\bullet 出现<0或者>2就是进入两次或者只有离开没有进入记录,数组记录字典序sort排序输出

代码

复制代码
    #include <bits/stdc++.h>
    using namespace std;
    
    map <string , int> mp;
    string st , s[20010] , ss[20010] , s1 = "enter" , s2 = "exit";
    int main(){
    	mp.clear();
    	int n , j = 0;
    	cin >> n;	
    	for(int i = 1; i <= n; ++i){
    		cin >> s[i] >> st;
    		if(st == s1)
    			mp[s[i]]++;
    		else if(st == s2)
    			mp[s[i]]--;
    		if(mp[s[i]] < 0 || mp[s[i]] > 1)
    			ss[++j] = s[i];
    	}
    	int kk = j;
    	sort(ss + 1 , ss + j + 1);
    	for(int i = 1; i <= j; ++i)
    		if(mp[s[i]] != 0)
    			ss[++kk] = s[i];
    	sort(ss + 1 , ss + kk + 1);
    	for(int i = 1; i <= kk; ++i)
    		if(ss[i] != ss[i + 1])
    			cout << ss[i] << " ";		
    	return 0; 
    }

组队竞赛

题目描述

有nn同学想要参加小爱组建的一支信息学竞赛队伍,每位同学有能力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 \geq 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

分析

\bullet 定义两个数组 , 读入后将能力值相同的直接复制到第二个数组中一起计算(此步骤可省略 , 删去无影响)

\bullet 和一年普及组题目海港相似

\bullet 结构体读入sort排序 , 从开头到结尾分成每个开始和结尾不同的区间每次遇到能力差大于X时 , 区间开头变换 , 同时计数总和减去所对应的热情度 , 每次打擂台作比较输出最大值

代码

复制代码
    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 10;
    
    struct nod{
    	int a , b;
    }x[MAXN] , xx[MAXN];
    
    bool cmp(nod p , nod q){
    	return p.a <= q.a;
    }
    
    int main(){
    	long long n , q;
    	cin >> n;
    	for(int i = 1; i <= n; ++i)
    		cin >> x[i].a >> x[i].b;
    	cin >> q;
    	sort(x + 1 , x + 1 + n , cmp);
    	long long ans = 0 , maxs = 0;
    	long long minv = 1 , maxv = 1;
    	while(maxv <= n){
    		maxs += x[maxv].b;
    		while(x[maxv].a - x[minv].a > q){
    			maxs -= x[minv].b;
    			minv++;
    		}
    		maxv++;
    		ans = max(ans , maxs);
    	} 
    	cout << ans << endl;
    	return 0; 
    }

或把能力值相同的统计到同一数组

复制代码
    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 10;
    
    struct nod{
    	int a , b;
    }x[MAXN] , xx[MAXN];
    
    bool cmp(nod p , nod q){
    	return p.a <= q.a;
    }
    
    int main(){
    	long long n , q;
    	cin >> n;
    	for(int i = 1; i <= n; ++i)
    		cin >> x[i].a >> x[i].b;
    	cin >> q;
    	sort(x + 1 , x + 1 + n , cmp);
    	int ii = 0;
    	for(int i = 1; i <= n; ++i){
    		if(x[i].a != xx[ii].a){
    			xx[++ii].a = x[i].a;
    			xx[ii].b = x[i].b;
    		}
    		else
    			xx[ii].b += x[i].b;
    	}
    	long long k = ii;
    	long long ans = 0 , maxs = 0;
    	long long minv = 1 , maxv = 1;
    	while(maxv <= k){
    		maxs += xx[maxv].b;
    		while(xx[maxv].a - xx[minv].a > q){
    			maxs -= xx[minv].b;
    			minv++;
    		}
    		maxv++;
    		ans = max(ans , maxs);
    	} 
    	cout << ans << endl;
    	return 0; 
    }

全部评论 (0)

还没有任何评论哟~