AcWing第33-37场周赛

在此记录,仅为方便复盘。

-第33场周赛

4207. 最长合法括号子序列

一个合法的括号序列满足以下条件:
序列()被认为是合法的。
如果序列X与Y是合法的,则XY也被认为是合法的。
如果序列X是合法的,则(X)也是合法的。
例如,()()()(())这些都是合法的。

现在,给定一个由 () 组成的字符串。

请你求出其中的最长合法括号子序列的长度。

注意,子序列不一定连续。

输入格式

共一行,一个由 ( 和 ) 组成的字符串。

输出格式

一个整数,表示最长合法括号子序列的长度。

数据范围

前五个测试点满足, 1≤输入字符串的长度≤10。
所有测试点满足,1≤输入字符串的长度≤106。

输入样例1:

(()))(

输出样例1:

4

输入样例2:

()()(()(((

输出样例2:

6
#include<iostream>
using namespace std;

int main(){
	char x;
	int flag=0,cnt=0,max=0;
	while(cin>>x){
		if(x=='('){
			flag++;
			cnt++;
		}
		if(x==')'&&flag>0){
			flag--;
			cnt++;
		}
		if(flag>=0)max=cnt-flag;
	}
	cout<<max;
	return 0;
}

4208. 电话号码

一个电话销售员正在整理他的电话簿。

电话簿中记录了他的全部客户的电话号码。

一个客户可能有不止一个电话号码。

不同客户可能拥有完全相同的电话号码。

电话簿中一共包含 n 条记录。

每条记录都是首先包含一个字符串,表示客户的姓名,然后包含一个整数,表示本条记录包含的电话号码数量,最后是本条记录所包含的电话号码。

不同客户的姓名两两不同,所以如果两条记录包含的客户姓名相同,那么我们认为这都是记录的同一人的电话信息。

同一记录中可能包含相同的电话号码,不同记录中也可能包含相同的电话号码。

在进行整理时,应遵守如下原则:

如果一个客户拥有多条记录,则需要将这些记录进行合并,每人只保留一条记录,去记录他的全部有效号码。
如果一个客户记录的多个电话号码完全相同,则只保留一个作为有效号码,其余的全部视为无效号码。 如果一个客户记录的两个不同电话号码 a 和 b
满足 a 是 b 的后缀,则号码 a 视为无效号码。 请输出整理后的电话记录。

输入格式

第一行包含整数 n,表示记录数量。

接下来 n 行,每行描述一条记录,首先包含一个长度不超过 10 的由小写字母构成的非空字符串,表示客户姓名,然后包含一个不超过 10的正整数,表示本条记录包含的号码数量,最后包含本条记录的所有号码,每个号码都是长度不超过 10 的由数字构成的非空字符串,可能包含前导 0。

输出格式

首先输出一个整数 m,表示完成整理后的记录数量。

接下来 m 行,每行输出一条记录信息,格式要求与输入一致。

同一行的数据之间用单个空格隔开。

记录的先后顺序随意,一条记录中的号码顺序随意。

数据范围

前三个测试点满足 1≤n≤4。

所有测试点满足 1≤n≤20。

输入样例1:

2
i 1 00123
m 1 00123

输出样例1:

2
m 1 00123 
i 1 00123 

这道题没写,之后补上

-第34场周赛

4210. 数字

给定一个大于 2 的十进制正整数 A。

该数字在 2∼A−1 进制表示下的各位数字之和均可以求出。

例如,数字 123 在 16 进制表示下,共有 2 位:第 1 位是 7,第二位是 11,各位数字之和为 18。

现在,请你将 A 在 2∼A−1 进制表示下的各位数字之和全部相加,并将得到的结果除以 A−2,最终结果以最简分数形式输出。

输入格式

一个十进制正整数 A。

输出格式

输出格式为 X/Y,其中 X 表示输出答案的分子,Y 表示输出答案的分母。

数据范围

前三个测试点满足 3≤A≤10。

所有测试点满足 3≤A≤1000。

输入样例1:

5

输出样例1:

7/3
#include<iostream>
using namespace std;
int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}
int main(){
	int a,i;
	cin>>a;
	int sum=0;
	int b;
	for(i=2;i<a;i++){
		b=a;
		while(b){
		sum+=b%i; //短除法
		b/=i;	
		}
	} 
	int d=gcd(sum,a-2);
	sum/=d;
	a-=2;
	a/=d;
	cout<<sum<<"/"<<a;
	return 0;
}

4211. 序列重排

给定一个长度为 n 的整数序列 a1,a2,…,an。

请你对序列进行重新排序(也可以保持原序列),要求新序列满足每个元素(第 1 个除外)都恰好是前一个元素的两倍或前一个元素的三分之一。

保证输入一定有解。

输入格式

第一行包含整数 n。

第二行包含 n 个整数 a1,a2,…,an。

输出格式

一行 n 个整数,表示排序后的序列。输出任意合法方案即可。

数据范围

前三个测试点满足 2≤n≤10。

所有测试点满足 2≤n≤100,1≤ai≤3×1018。

输入样例1:

6
4 8 6 3 12 9

输出样例1:

9 3 6 12 4 8 
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

typedef long long ll;

int get(ll x,ll b){
	int res=0;
	while(x%b==0){
	res++;
	x/=b;
	}
	return res;
}
int main(){
	int n;
	cin>>n;
	vector<ll> t[n];
	int i;
	for(i=0;i<n;i++){
		ll x;
		cin>>x;
		t[i]={get(x,2),-get(x,3),x};
	}
	sort(t,t+n);
	for(i=0;i<n;i++){
		cout<<t[i][2]<<" "; 
	}
	return 0;
}

-第35场周赛

4213. 最小结果

有四个整数 a,b,c,d。

有三个操作符 op1,op2,op3,每个操作符要么是 *(表示乘法),要么是 +(表示加法)。

现在,我们要进行如下操作:

从现有整数中选出两个,按 op1 进行运算,得到结果。将选出的两个整数舍弃,并将结果保留。此时我们还剩下三个整数。
从现有整数中选出两个,按op2 进行运算,得到结果。将选出的两个整数舍弃,并将结果保留。此时我们还剩下两个整数。
从现有整数中选出两个,按 op3进行运算,得到结果。将选出的两个整数舍弃,并将结果保留。此时我们只剩下一个整数。
我们希望,最后剩下的一个整数尽可能小。

输入格式

第一行包含四个整数 a,b,c,d。

第二行包含三个操作符 op1,op2,op3,每个操作符要么是 *,要么是 +。

输出格式

输出最后剩下的一个整数的最小可能值。

数据范围

所有测试点满足 0≤a,b,c,d≤1000。

输入样例1:

1 1 1 1
+ + *

输出样例1:

3
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;

char op[5];
LL ans=1e18;

void dfs(vector<LL> v,int u){
	if(v.size()==1)ans=min(ans,v[0]);
	else{
		for(int i=0;i<v.size();i++){
			for(int j=i+1;j<v.size();j++){
				vector<LL> t;
				for(int k=0;k<v.size();k++){
					if(k!=i&&k!=j){
						t.push_back(v[k]);
					}
				}
					if(op[u]=='*')t.push_back(v[i]*v[j]);
					else t.push_back(v[i]+v[j]);
			dfs(t,u+1);
			}
		}
	}
}
int main(){
	vector<LL> v(4);
	int i,j;
	for(i=0;i<4;i++)cin>>v[i];
	for(i=0;i<3;i++)cin>>op[i];
	dfs(v,0);
	cout<<ans<<endl;
	return 0;
}

4214. 三元组

给定两个长度为 n 的整数序列 s1,s2,…,sn 和 c1,c2,…,cn。

请你找到一个三元组 (i,j,k),满足以下所有条件:

i<j<k si<sj<sk ci+cj+ck 尽可能小 输出 ci+cj+ck 的最小可能值。

输入格式 第一行包含整数 n。

第二行包含 n 个整数 s1,s2,…,sn。

第三行包含 n 个整数 c1,c2,…,cn。

输出格式

如果满足条件的三元组不存在,则输出 −1。

否则,输出 ci+cj+ck 的最小可能值。

数据范围

前 5 个测试点满足 3≤n≤10。
所有测试点满足 3≤n≤3000,1≤si≤109,1≤ci≤108。

输入样例1:

5
2 4 5 4 10
40 30 20 10 40

输出样例1:

90
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int s[3001],c[3001];
const int INF=5e8;
int main(){
	int n;
	cin>>n;
	int i;
	int res=INF;
	for(i=0;i<n;i++)cin>>s[i];
	for(i=0;i<n;i++)cin>>c[i];
	for(int j=0;j<n;j++){
		int left=INF;
		for(i=0;i<j;i++){
			if(s[i]<s[j])left=min(left,c[i]);
		}
		int right=INF;
		for(int k=j+1;k<n;k++){
			if(s[k]>s[j])right=min(right,c[k]);
		}
		res=min(res,left+c[j]+right);
	}
	if(res==INF)res=-1;
	cout<<res<<endl;
	return 0;
}

-第36场周赛
没有,之后补上

-第37场周赛

4297. 截断数组

给定一个长度为 n 的数组 d1,d2,…,dn。

现在,要将该数组从中间截断,得到三个子数组(可以为空)。

不妨设第一个子数组包含 a 个元素,第二个子数组包含 b 个元素,第三个子数组包含 c 个元素。

那么三个子数组的各元素之和 sum1,sum2,sum3 依次为:

sum1=∑1≤i≤adi,sum2=∑a+1≤i≤a+bdi,sum3=∑a+b+1≤i≤a+b+cdi。

注意,空数组的各元素之和为 0。

我们希望截断后的三个子数组满足:

sum1=sum3。 满足上一条件的情况下,sum1 尽可能大。 请你计算并输出 sum1 的最大可能值。

显然,本题一定有解,因为可以令 a=0,b=n,c=0。

输入格式

第一行包含整数 n。

第二行包含 n 个整数 d1,d2,…,dn。

输出格式

输出一个整数,表示 sum1 的最大可能值。

数据范围

前 6 个测试点满足 1≤n≤10。

所有测试点满足 1≤n≤2×105,1≤di≤109。

输入样例1:

5
1 3 1 1 4

输出样例1:

5
#include<iostream>
using namespace std;
int main(){
	int n;
	cin>>n;
	int a[n];
	int i;
	for(i=0;i<n;i++){
		cin>>a[i];
	}
	long long sum1=0,sum2=0,sum=0;
	for(i=0;i<=n;){
		if(sum1==sum2){
		sum=sum1;
		sum1+=a[i];
		sum2+=a[n-1];
		i++;
		n--;
		}else if(sum1>sum2){
			sum2+=a[n-1];
			n--;
		}else if(sum1<sum2){
			sum1+=a[i];
			i++;
		}
	}
	cout<<sum;
	return 0;
}

4298. 搭档

有 n 个男孩,每个人的魅力值依次为 a1,a2,…,an.

有 m 个女孩,每个人的魅力值依次为 b1,b2,…,bm。

学校举办舞会,希望选出尽可能多的男女搭档参加。

已知,当一对男女的魅力值相差不超过 1 时,他们才会愿意组成搭档。

请问,最多可以同时凑出多少对搭档参加舞会。

注意:

不能男男配对或女女配对。 每个男生最多只能和一个女生配对,反之亦然。 输入格式 第一行包含整数 n。

第二行包含 n 个整数 a1,a2,…,an。

第三行包含整数 m。

第四行包含 m 个整数 b1,b2,…,bm。

输出格式

一个整数,表示最大可能对数。

数据范围

前 6 个测试点满足 1≤n,m≤5,

所有测试点满足 1≤n,m≤100,1≤ai,bi≤100。

输入样例1:

4
1 4 6 2
5
5 1 5 7 9

输出样例1:

3
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int main(){
	int n,m,i,j;
	cin>>n;
	int a[n];
	for(i=0;i<n;i++){
		cin>>a[i];
	}
	cin>>m;
	int b[m];
	for(i=0;i<m;i++){
		cin>>b[i];
	}
	sort(a,a+n);
	sort(b,b+m);
	int ans=0;
	for(i=0,j=0;i<n;){
		if(j==m)break; 
		if(abs(a[i]-b[j])<=1){
			ans++;
			i++;
			j++;
		}else if(a[i]>b[j])j++;
		else if(a[i]<b[j])i++;
		
	}
	cout<<ans;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值