codeforce B题题单整理

众所周知,codeforce div2AB两题以思维题为主,极少涉及算法知识。对于新手来说,能够快速并准确地解决B题是上分的关键。当AB题的写题量达到一定程度时,可以发现所谓思维题也有套路可循。据此,笔者将套路归纳为几大块,并收纳了一些具有一定代表性的题目。
本题单持续更新。

模拟

这里放上一些对模拟码力要求较高而解题性质较明显的题目。
732(div2) A.AquaMoon and Two Arrays
题意:虽然是A题,但还是有点码力要求的 给两个序列,可以对第一个序列进行任意次操作,每次操作可选取两个数,使其中一个数加一,另一个数减一,问能否进行小于等于100次的操作,使第一个序列变成第二个序列,并将操作过程输出。
思路:纯模拟+贪心。将所有数分为两部分,要加的和要减的,把要加的差减去要减的,可以发现最后两差分数组所有数必为零,不为零输出-1。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
using namespace std;
struct Node{
   
	int x,y;
};
bool cmp(Node x,Node y){
   
	return x.y < y.y;
}
signed main(){
   
	IOS
	int t;cin>>t;
	while (t--){
   
		int n;cin>>n;
		int a[n+1],b[n+1];
		for (int i=1;i<=n;i++) cin>>a[i];
		for (int i=1;i<=n;i++) cin>>b[i];
		Node d1[n+1],d2[n+1];
		//d1存要加的,d2存要减的
		//处理d1 d2数组 y存差值 x存下标
		int cnt = 0,snt = 0;
		for (int i=1;i<=n;i++){
   
			int d = a[i] - b[i];
			if (d<0){
   
				cnt++;
				d1[cnt].y = -d;
				d1[cnt].x = i;
			}
			else if (d>0){
   
				snt++;
				d2[snt].y = d;
				d2[snt].x = i;
			}
		}
		//贪心 根据值排序
		sort(d1+1,d1+cnt+1,cmp);
		sort(d2+1,d2+snt+1,cmp);
		vector<pair<int,int>>op;
		//op存操作过程
		bool flag = 0;
		//flag判断能否成功变成
		//模拟部分
		for (int i=1;i<=cnt;i++){
   
			int dd = d1[i].y;
			//取出一个d1 然后暴力遍历d2
			for (int j=1;j<=snt;j++){
   
				if (d2[j].y>=dd){
   //d2 比 dd大 直接减
					d2[j].y -= dd;//d2减去dd贡献
					for (int k=1;k<=dd;k++){
   
						op.push_back({
   d2[j].x,d1[i].x});
					}//存操作数
					dd = 0;//dd清零
					break;
				}
				else {
   
					for (int k=1;k<=d2[j].y;k++){
   
						op.push_back({
   d2[j].x,d1[i].x});
					}
					dd -= d2[j].y;//dd减去贡献
					d2[j].y = 0;//d2变为0
				}
			}
			if (dd){
   //d1经过遍历d2后都不能变成0 说明无法变成
				flag = 1;
				break;
			}
		}
		//如果可以变成第二个序列,d2数组在操作后必为零
		for (int i=1;i<=snt;i++){
   
			if (d2[i].y){
   
				flag = 1;//不为零就说明变成不了
				break;
			}
		}
		//输出部分
		if (flag) cout<<-1<<endl;
		else {
   
			cout<<op.size()<<endl;
			for (auto it:op){
   
				cout<<it.first<<" "<<it.second<<endl;
			}
		}
	}
}

751(div2) B. Divine Array
题意:给一串数,进行无数次操作,每次操作让每个数变成它出现的次数。进行q次询问,询问第x下标第k轮操作的值
思路:模拟+思维。对于无数次操作的题目,显然是去找一个“不动结点”,即发现哪次操作后数组值不会改变。手模一遍后发现,当每个数的数值等于它出现次数时,它就不变了。故用桶模拟出这个过程即可。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
using namespace std;
signed main(){
   
	IOS
	int t;cin>>t;
	while (t--){
   
		int n;cin>>n;
		int a[n+1];
		map<int,int>mp;
		int m[n+1][n+1];
		//m[i][k]第k次操作第i个数的值
		//mp记录每个数出现次数
		for (int i=1;i<=n;i++){
   
			cin>>a[i];
			m[i][0] = a[i];
			mp[a[i]]++;
		}
		int cnt = 0;
		while (1){
   
			bool flag = 0;
			cnt++;
			//cout<<"cnt = "<<cnt<<endl;
			for (int i=1;i<=n;i++){
   
				m[i][cnt] = mp[m[i][cnt-1]];
				//cout<<m[i][cnt]<<" ";
				//mp[mmp[a[i]]]++;
			}
			mp.clear();
			for (int i=1;i<=n;i++){
   
				mp[m[i][cnt]]++;
			}
			for (int i=1;i<=n;i++){
   
				if (mp[m[i][cnt]]!=m[i][cnt]) flag = 1;
			}
			//cout<<endl;
			if (flag) continue;
			else break;//当所有数等于出现次数时 不会再改变 跳出循环
		}
		int q;cin>>q;
		while (q--){
   
			int x,k;cin>>x>>k;
			if (k>cnt) k = cnt;
			cout<<m[x][k]<<endl;
		}
		//cout<<"......."<<endl;
	}
}

705(div2) B. Planet Lapituletti
题意:自定义小时进制h,分钟进制m,给出当前时间,求最近的在镜子里合法的未来时间。
思路:模拟+简单规律。可以发现镜子里的合法时间仅包括0,1,2,5,8五个数字,故暴力枚举所有合法时间和其镜子里的映射时间,判断两者是否均符合进制,记录离当前时间最近的时间即可。

#include <bits/stdc++.h>
#define INF 0x7f7f7f7f 
using namespace std;
char s[] = {
   '0','1','2','5','8'};
string s1[30];
int cnt;
int at(string s){
   //计算现实时间 
	int ans = 0;
	for (int i=0;i<s.si
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值