Codeforces Round #653 (Div. 3)(ABCDE题解)

在这里插入图片描述
在这里插入图片描述
题目大意:
给你 x , y , n x,y,n x,y,n,要你在 [ 1 , n ] [1,n] [1,n]内找到最大 n u m num num的数满足 n u m num num % x = y x=y x=y
思路:
一开始想的枚举 x x x的倍数,然后超时了,就只能往数学的方向思考了,满足要求的最大的数一定是分布的 n n n那里,所以我们可以直接 n − ( n n-(n n(n% x ) + y x)+y x)+y就行了,意思是用 n n n减去超过 x x x的那一部分,那么剩下的一定% x = 0 x=0 x=0,所以再加上 y y y就行了,不过有可能 n − ( n n-(n n(n% x ) + y x)+y x)+y > n >n >n,所以对于 > n >n >n只需要多减去一个 x x x即可。
代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long int ll;
void solved(){
	ll x,y,n;cin>>x>>y>>n;
	if(n % x == y){
		cout<<n<<endl;
	}else{
		if(n - (n % x) + y <= n)
		cout<<n - (n % x) + y<<endl;
		else cout<<n - (n % x) - x + y<<endl;
	}
} 
int main(){
	int t;cin>>t;
	while(t--)
	solved();
	return 0;
}

在这里插入图片描述
在这里插入图片描述
题目大意:
给你一个数 n n n,对于这个数你可以选择两种操作,那么对它 ∗ 2 *2 2,要么 / 6 /6 /6(必须整除),问你从 n n n 1 1 1最少操作步数是多少,如果不能得到 1 1 1输出 − 1 -1 1
思路:
这个题往数学想了一会,发现没什么思路,然后注意到 n = 1 e 9 n=1e9 n=1e9,然后每次 ∗ 2 o r / 6 *2 o r/6 2or/6,时间复杂度是 O ( l o g n ) O(logn) O(logn),所以模拟写了一发暴力 a c ac ac.
代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long int ll;
void solved(){
	ll x;cin>>x;
	int cnt = 0;
	while(x != 1){
		if(x >= 1e9){
			cout<<"-1"<<endl;return ;
		}
		if(x % 6 == 0)x /= 6;
		else x *= 2;
		cnt++;
	}
	cout<<cnt<<endl;
}
int main(){
	int t;cin>>t;
	while(t--)solved();
	return 0;
} 

在这里插入图片描述
在这里插入图片描述
题目大意:
给你一个字符串,问你将一个字符串变成好的字符串最少需要多少操作,好的字符串是 t = " ( ) " t="()" t="()",如果 a , b a,b a,b是好的字符串那么 a + b 或 者 ( a ) a+b或者(a) a+ba也都是好的字符串,你可以选择 i , 1 < = i < = n i,1<=i<=n i,1<=i<=n,然后把 s [ i ] s[i] s[i]插入字符串头部或者尾部。
思路:
看到括号就会想到栈,用栈模拟一下就行了,如果栈空切 s [ i ] = ′ ) ′ s[i]=')' s[i]=)则说明操作次数+1,因为你要把这个括号自动后面去,如果栈不空且 s [ i ] = ′ ) ′ s[i]=')' s[i]=)说明匹配, p o p pop pop一下,否则入栈。
代码:

#include<bits/stdc++.h>
using namespace std;

void solved(){
	int n;cin>>n;
	string s;cin>>s;
	stack<char>st;
	int cnt = 0;
	for(int i = 0; i < s.size(); i++){
		if(st.empty() && s[i] == ')'){
			cnt++;continue;
		}
		if(!st.empty() && s[i] == ')'){
			st.pop();continue;	
		}
		st.push(s[i]);
	}
	cout<<cnt<<endl;
}
int main(){
	int t;cin>>t;
	while(t--)solved();
	return 0;
}

在这里插入图片描述
在这里插入图片描述
题目大意:
给你一个长度为 n n n的数组和一个整数 k k k,问你将数组所有元素都能够被 k k k整除,需要操作最少的次数是多少?你有两种操作,第一个是给数组某个元素 + x ( x +x(x +x(x一开始为0),然后 x + = 1 x+=1 x+=1,第二种操作是 x + = 1 x+=1 x+=1
思路:
用对每个数 a [ i ] = k − a [ i ] a[i] = k - a[i] a[i]=ka[i] % k k k,求一下每个数能被 k k k整除还需要多少步骤,一开始写了一个玄学优先队列,最终弃疗了,加入 a [ ] = 1 , 2 , 3 , 4 , 5 a[]={1,2,3,4,5} a[]=1,2,3,4,5其实我们只需要输出5就行了,因为在之前的数可以分配给小的数,也就说答案就是 m a x ( a i ) max(ai) max(ai),但是有可能有多少相同的数,例如 a [ ] = 1 , 1 , 1 , 2 , 2 , 2 , 2 , 2 , 4 , 5 , 6 , 8 a[]={1,1,1,2,2,2,2,2,4,5,6,8} a[]=1,1,1,2,2,2,2,2,4,5,6,8那么这个时候 m a x ( a i ) max(ai) max(ai)显然不是答案,因为要满足 2 2 2 x x x需要多跑几个来回(在modk意义下),那么容易发现答案就是出现次数最多的那个数,它的操作次数为 a [ i ] + k ∗ ( n u m i − 1 ) , n u m i a[i]+ k * (numi - 1),numi a[i]+k(numi1)numi是最多出现的那个数的次数,把这两种清空整合在一起取一个 m a x max max就行了。
代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 10;
typedef long long int ll;
ll n,k,x;
ll a[maxn];
int cmp(int a,int b){
	return a > b;
}
void solved() {
	ll n,k;cin>>n>>k;
	for(int i = 1; i <= n; i++){
		cin>>a[i];
		if(a[i] % k == 0)a[i] = 0;
		else a[i] = k - a[i] % k;
	}
	sort(a + 1, a + 1 + n,cmp);
	ll ans = 0;
	for(int i = 1; i <= n; i++){
		if(a[i] == 0){
			if(i == 1){
				cout<<"0"<<endl;return ;
			}
			break;
		}
		if(a[i] != a[i + 1]){
			ans = max(ans,a[i]);
		}else{
			ll cnt = 0;
			while(i + 1 <= n && a[i] == a[i + 1])
				i++,cnt++;
			ans = max(k * cnt + a[i],ans);
		}
	}
	cout<<ans + 1<<endl;
}
int main() {
	int t;cin>>t;
	while(t--)solved();
	return 0;
}

在这里插入图片描述
在这里插入图片描述
题目大意:
有两个人,有 n n n本书,每本书有 ( t , a , b ) (t,a,b) (t,a,b), t t t表示看完这本书需要的时间, a = 1 a=1 a=1表示第一个人可以选, b = 1 b=1 b=1表示第二个人可以选,如果 a , b a,b a,b同时为一表示他们都可以同时看,问你每个人看完 k k k本书的最少时间。
思路:
很显然是贪心,关键是怎么贪,我们可以将这些书分成四类。
第一类:两人都可以看
第二类:只有第一个人可以看
第三类:只有第二个人可以看
第四类:两人都不可以看
第四类可以不用考虑,我们先对第一,二类升序排序,然后同时加入第一类,这样可以保证第一个人读最优的书的同时保证第二个人也是最优,然后再对第三类升序选择前 k k k个就行了。
代码:

#include<bits/stdc++.h>
using namespace std;

void solved(){
	int n,k;cin>>n>>k;
	vector<int>all;
	vector<int>a;
	vector<int>b;
	for(int i = 1; i <= n; i++){
		int t,x,y;
		cin>>t>>x>>y;
		if(x == 1 && y == 1){
			all.push_back(t);
		}else if(x == 1){
			a.push_back(t);
		}else if(y == 1){
			b.push_back(t);
		}
	}
	sort(a.begin(),a.end());
	sort(b.begin(),b.end());
	for(int i = 0; i < min(a.size(),b.size()); i++){
		all.push_back(a[i] + b[i]);
	}
	if(all.size() < k){
		cout<<"-1"<<endl;return ;
	}
	sort(all.begin(),all.end());
	int ans = 0;
	for(int i = 0; i < k; i++){
		ans += all[i];
	}
	cout<<ans<<endl;
}
int main(){
	solved();
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值