JG-OJ记录-第七次线上赛:20-21(2)第0次线上赛(智商康复训练)

*1:签到题-5
*2:区间并集
*3:特殊的01串
*4:公因数-2
*5:WSAD
*6:数组的贡献值

1:签到题-5

描述
嘉庚学院开展了为期两周的线上教学活动,其中出勤是一个很重要的指标。

每次有 n 个同学应该来参加线上课程,他们都有自己独特的学号来进行签到。

但总有一个同学睡过了头也就是他没有签到,要接受爆照的处罚(奖励),你能帮老师找出是谁这么幸运么?

输入
只有一组案例。

第一行是一个正整数 n,表示本次课程应该有 n 个同学来参与。(2 <= n <= 1e5)

第二行是 n 个互不相同的正整数 xi,分别表示这 n 个同学独特的学号。(1 <= xi <= 1e9)

第三行是 n - 1 个互不相同的正整数,表示老师给出的已经签到的 n - 1 个同学的学号。(保证是这节课应该来的同学的学号)

输出
输出一个正整数,表示没有签到同学的学号,然后换行。

样例输入
4

2 3 4 8

8 3 4

样例输出
2

HINT
老师给出的学号和应签到的学号都不一定有序。

来源
20-21(2)第0次线上赛

解:
1、(最简单的)(来自大佬涂涂)第一次输入的和-第二次输入的和。
2、(来自IST大佬)map容器 key-value学号不重复>set>s. erase>输出
(太难不细说)(俺不会-理直气壮)
3、两个一维数组进行sort排序,第一个对不上号的就是没到的(下面代码)。

#include<iostream>
#include<algorithm>
//algorithm-sort
using namespace std;
int main()
{
    
    
	int n;
	cin>>n;
	int *a=new int[n]();
	int *b=new int[n-1]();
	for(int i=0;i<n;i++)
	{
    
    
		cin>>a[i];
	}
	sort(a,a+n-1);
	for(int i=0;i<n-1;i++)
	{
    
    
		cin>>b[i];
	}
	sort(b,b+n-2);
	bool sc=0;
	for(int i=0;i<n-1;i++)
	{
    
    
		if(sc==0)
		{
    
    
			if(a[i]!=b[i])
			{
    
    
				cout<<a[i]<<endl;
				sc=1;
				break;
			}
		}
	}
	if(sc==0) cout<<a[n-1]<<endl;
	delete []a;
	delete []b;
	return 0;
}

2:区间并集

描述
存在 n 个区间:a1、a2、…… 、an。

求 a1 ∪ a2 ∪ a3 ∪ …… ∪ an。

输入
只有一组案例。

第一行正整数 n 表示区间的个数。(1 <= n <= 1e5)

然后是 n 行,每行包含两个正整数 L 和 R,分别表示一个区间左右端点,即 [ L,R ]。(0 <= L <= R <= 1e10)

输出
根据左端点的大小,从小到大输出取并集后的每个区间。

每个区间的左端点和右端点之间用空格隔开,每次输出以后都要换行。

样例输入
6

1 2

1 4

8 10

8 9

5 6

6 7

样例输出
1 4

5 7

8 10

HINT
[1,2] 区间和 [1,4] 区间取并集后变为 [1,4]

[5,6] 区间和 [6,7] 区间取并集后变为 [5,7]

[8,9] 区间和 [8,10] 区间取并集后变为 [8,10]

来源
20-21(2)第0次线上赛

解:
1、结构体存储每一次输入的L、R(左右端),然后sort排序,排序规则看compare,然后记录第一个L、R为l、r,后面有L大于记录的r时输出存储的l、r,存储新的L、R,如果后面的L不大于记录的r则合并合集,取俩合集(存储的l、r和该次的L、R)中最小的左端为l和最大的右端为r。(下面代码)

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long int ll;
struct qj
{
    
    
	ll L;
	ll R;
};
qj s[100005];
bool compare(qj a,qj b)
{
    
    
	if(a.L==b.L)
	{
    
    
		return a.R<b.R;
	}
    return a.L<b.L;
}
int main()
{
    
    
	ll n;
	cin>>n;
	for(ll i=1;i<=n;i++)
	{
    
    
		cin>>s[i].L>>s[i].R;
	}
	//cout<<"opening"<<endl; 
	sort(s,s+n+1,compare);
	ll l=0,r=0;
	for(ll i=1;i<=n;i++)
	{
    
    
		if(i==1)
		{
    
    
			l=s[i].L;
			r=s[i].R;
		}
		else
		{
    
    
			if(s[i].L>r)
			{
    
    
				cout<<l<<" "<<r<<endl;
				l=s[i].L;
				r=s[i].R;
			}
			else
			{
    
    
				if(s[i].R>r)
				{
    
    
					r=s[i].R;
				}
			}
		}
	}
	cout<<l<<" "<<r<<endl;
	return 0;
}

3:特殊的01串

描述
我们定义一个字符串是特殊的01串:

1.空串是特殊的01串。
2.仅由字符 0 和 1 构成且任意两个相邻的字符不都为 1。

现在请你构造一个长度为 n 的特殊的01串,请问你可以构造多少个?

输入
第一行是一个正整数 T 代表测试案例的数量。(1 <= T <= 1e5)

每组案例是一个整数 n,代表构造字符串的长度。(0 <= n <= 1e6)

输出
针对每组案例,输出你可以构造多少个,然后换行。

由于答案可能很大,所以你只需要输出它对 998244353 取模以后的结果。

样例输入
1
3

样例输出
5

HINT
长度为 3 的特殊的01串可以是 100 010 001 101 000。

来源
20-21(2)第0次线上赛

解:
1、找规律,数组存储(下面代码)。

#include<iostream>
#include<cstring>
#define mod 998244353
using namespace std;
int ans[1000005];
int main()
{
    
    
	memset(ans,0,sizeof(ans));
	ans[0]=1;ans[1]=2;ans[2]=3;ans[3]=5;
	for(int i=4;i<=1000005;i++)
	{
    
    
		ans[i]=(ans[i-1]+ans[i-2])%mod;
	}
	int T;
	cin>>T;
	for(int f=1;f<=T;f++)
	{
    
    
		int n;
		cin>>n;
		cout<<ans[n]<<endl;
	}
	return 0; 
}

4:公因数-2

描述
有 n 个数字,求它们的公共质因数。
输入
只有一组案例。

第一行是一个正整数 n 代表数字的个数。(1 <= n <= 1e5)

然后是 n 个正整数,对于每一个正整数 x 都有 1 <= x <= 1e5。

输出
按从小到大的顺序依次输出这 n 个数字的公共质因数,每两个数字之间用空格隔开,最后一个数字后面没有空格。

如果它们没有公共质因数则输出 No。

最后换行。

样例输入
3

6 12 18

样例输出
2 3

HINT
来源
20-21(2)第0次线上赛

解:
1.筛法筛出1e5以下的素数,排序所给的数字以后循环判断每个素数是否是公因数(下面代码)。
2.(不需要筛法)(来自CST大佬)排序从小到大——拿a[0]找小于等于它的质数——得到质数判断是不是公因数——是——输出。

#include<iostream>
#include<cstring>
using namespace std;
const int N=100005;
int p[N];
int prime[N];
int cnt=0;
void xxs()
{
    
    
	for (int i = 2; i <= N; i++)
	{
    
    
	if(p[i] == 0)
	{
    
    
		p[i]=i;
		prime[cnt++]=i;
	}
	for (int j = 0;j<cnt;j++)
	{
    
    
		if (prime[j]>p[i]||prime[j]*i>N)
		{
    
    
			break;
		}
		p[prime[j]*i]=prime[j];
	}
	}
}
int main()
{
    
    
	bool sc=0;
	int sz[100005];
	memset(sz,0,sizeof(sz));
	xxs();
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
    
    
		cin>>sz[i];
	}
	for(int i=0;i<cnt;i++)
	{
    
    
		for(int j=1;j<=n;j++)
		{
    
    
			if(sz[j]%prime[i]!=0) break;
			else if(j==n)
			{
    
    
				if(sc==0)
				{
    
    
					cout<<prime[i];
					sc=1;
				}
				else cout<<" "<<prime[i];
			}
		}
	}
	if(sc==0) cout<<"No";
	cout<<endl;
	return 0;
} 

5:WSAD

描述
罗少在玩一个游戏,用 W S A D 分别控制角色进行 上 下 左 右 移动,我们可以把地图看作一个二维平面,罗少初始站在原点,现在他操作了 n 次,请你输出他的位置。

输入
第一行是一个正整数 n 代表测试案例的数量。(1 <= n <= 100)

每组案例是一个仅包含字符WSAD的字符串 t 代表罗少的操作。(1 <= length(t) <= 100)

输出
针对每组案例,输出罗少操作以后所在位置的横纵坐标,两者之间用空格隔开,然后换行。

样例输入
2

WWW

SSD

样例输出
0 3

1 -2

HINT
来源
20-21(2)第0次线上赛

解:
1、循环判断字符串每一个字符(下面代码)。
2、(来自CST大佬)使用count计算WASD的个数,直接计算。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
    
    
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
    
    
		int x=0,y=0;
		string s;
		cin>>s;
		int lg=s.size();
		for(int j=0;j<=lg;j++)
		{
    
    
			if(s[j]=='W') y++;
			if(s[j]=='S') y--;
			if(s[j]=='A') x--;
			if(s[j]=='D') x++;
		}
		cout<<x<<" "<<y<<endl;
	}
	return 0;
}

6:数组的贡献值

描述 罗少经常刷题,这天他又看到了一道很有意思的题目。

给定一个长度为 n 的数组,定义数组的贡献值为数组中 每个数首次出现的位置 * 每个数出现的次数 之和(相同的数字只计算一次)。

例如:1 2 2 3 1,数字 1 首次出现的位置是 1,总共出现了 2 次,所以提供 1 * 2 = 2 的贡献值,数字 2 是 2 * 2 = 4,数字 3 是 4 * 1 = 4,因此这个数组的贡献值为 2 + 4 + 4 = 10。

但很显然这样是难不倒罗少的,所以附加了一个条件,你可以任意改变数组中数的位置,问改变后数组最大的贡献值是多少?

输入
第一行是一个正整数 T 代表测试案例的数量。(1 <= T <= 10)

每组案例包含一个正整数 n ,代表数组的长度。(1 <= n <= 100000)

然后是 n 个整数 ai。(|ai| <= 10000)

输出
针对每组案例,输出改变数字位置后可以得到的最大数组贡献值,然后换行。

样例输入
2
4
1 2 1 2
4
1 1 2 2

样例输出
8
8

HINT
注意:数组也可以不发生改变。

对于样例1:1 2 1 2

改变前数组的贡献值为 1 * 2 + 2 * 2 = 6

你可以把他改为 1 1 2 2 或者 2 2 1 1 得到更大的数组的贡献值 8。

来源
20-21(2)第0次线上赛

解:
无(太难了QWQ)

猜你喜欢

转载自blog.csdn.net/Fei_WuYan/article/details/114450933
今日推荐