Codeforces Round #847 (Div. 3) A~E题解(详细题解)【一起来打cf吧】

 前言 

大家好啊,这里是幸麟

🧩 一名普通的大学牲,最近在学算法,希望这篇题解对你有帮助

🧩codeforce id:XingRin

🧩本文栏目:一起来打cf吧

比赛时间好晚,打完状态真的很差

第一次打div3难度的,比div2简单多了

还是比较适合像我这样的萌新的

本篇所有题目难度预计在div2的A~B题间

全部是思维题,不涉及算法,请各位放心食用

目录

A. Polycarp and the Day of Pi

B. Taisia and Dice

C. Premutation

D. Matryoshkas

E. Vlad and a Pair of Numbers


A. Polycarp and the Day of Pi

题目链接:Problem - A - Codeforces

题目:

 大意:

今天是圆周率之日,Polycarp同学想知道自己写的圆周率哪里不对,他会输入一个数(小数点去除,并且最多30位),希望你告诉他,他写对了前几位

例如315,他只写对前两位数字(真正的应该是314)

比较简单,只要一一对比每一个数字就可以了

#include <iostream>
#include <string>
using namespace std;
string s="314159265358979323846264338327";
int main()
{
	int t;
	cin>>t;
	string s1;
	while(t--)
	{
		cin>>s1;
		int num=0;
		for(int i=0;i<s1.size();i++)
		{
			if(s1[i]!=s[i])
			{
				break;
			}
			num++;
		}
		cout<<num<<endl;
	}
	return 0;
}

B. Taisia and Dice

题目链接:Problem - B - Codeforces

题目:

 题目大意:Taisia有n个骰子,这个骰子有6面,每一次投掷可能有6种点数(1,2,3,4,5,6),其实就是正常的骰子

有一次在抛完后,Taisia统计了n个骰子的点数之和s,统计完后他家的猫把点数最大的那颗骰子拿走了,于是他又统计了剩下n-1个骰子的点数r,

他将这些数据告诉你,希望你可以输出符合条件的n个骰子的点数,如果有多种,输出一种就可以了

例如

n=2,s=2,r=1

那么两个骰子可能的点数就是  1   1

将其输出便可

 只要输出一种可能的情况,我比较喜欢优先输出大的点数

我们目前r点剩余点数,我们将其分配给n-1个骰子便可

具体可以看一下注释

#include <iostream>
#include <string>
using namespace std;
 
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,s,r;
		cin>>n>>s>>r;
		int a=s-r;
		cout<<a<<' ';
		while(r)//还有r点剩余点数可以分配
		{
			if(r>=a && r-a>=n-2)//剩余点数>想分配的点数
			{
				cout<<a<<' ';//并且分配完后,剩下的骰子至少可以分配一点数
				r-=a;
				n--;
			}
			else//减少想分配的点数的大小
			{
				a--;
			}
		}
		cout<<'\n';
	}
	return 0;
}

C. Premutation

链接:Problem - C - Codeforces

题目:大晚上看的让人眼花缭乱,但是其实还是比较简单的

 大意:

有一个序列,其中包含了n个元素,1~n在其中都有(例如 4 2 1 3)

Kristina同学将其写在白板上,但是他的写法比较特别,他会写n行

每一行跳过一个对应的数字,写n-1个数字

例如 4 2 1 3中

第一行写下的是:2 1 3,跳过第一个数字4

第二行:4 1 3

接下来两行也按该规律

他将他在白板上的内容打乱了行序给你,希望你可以还原出原先的序列,并将其输出

思路

’其实蛮简单的,我们只需要找到原先序列的首元素,然后将其与每行的首元素对比,如果发现不同,那么这不同的一行就对应这原先2~n位置的元素,将原先序列的首元素和这一行输出即可

#include <iostream>
#include <string>
using namespace std;
int a[10010][110];
 
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int ans[110]={0};
		int n;
		cin>>n;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n-1;j++)
			{
				scanf("%d",&a[i][j]);
			} 
		}
		if(a[1][0]==a[0][0] || a[1][0]==a[2][0])//找首元素
		{
			ans[0]=a[1][0];
		}
		else
		{
			ans[0]=a[0][0];
		}
		for(int i=0;i<n;i++)
		{
			if(ans[0]!=a[i][0])
			{
				for(int j=0;j<n-1;j++)
				{
					ans[1+j]=a[i][j];
				}
			}
		}
		for(int i=0;i<n;i++)
		{
			printf("%d ",ans[i]);
		}
		cout<<endl;
	}
	return 0;
}

D. Matryoshkas

这是昨天写的最后一道题目,写到这题已经第二天了,有点写不动了,如果换个时间可能会好些

链接:Problem - D - Codeforces

题目:

样例 

大意:开头介绍了一下套娃,大的套娃可以将小的套娃套进去,但是有要求这个被套进去的套娃,必须只比那个大的套娃小一个尺寸,这边用数字代表尺寸

例如4 3 2 1,这四个套娃可以被套在一起

而4 2 1,只有2 1 可以套一起

给你n个套娃,希望你将其套完后场上的套娃数量最少,输出这个最小的数量

如2 2 3 4 3 1

套完后场上最少的套娃数量是2(因为1 2 3 4可以套成一个,2 3可以套成一个)

思路:

我们可以先将套娃整理一下,按尺寸大小排好

假设我们正在套娃中,那我们可以先把套娃分为2种情况,还在套的娃和已经确定不能再套的娃

如何确定不能再套的娃,有以下这些情况

①我们找不到比手中还在套的娃大一个尺寸的套娃了,那么手中还在套的娃便已经不能在套了

例如1 2 4, 我们在套1 2后,发现没有3了,那么1 2就不能继续套了

②小1尺寸的套娃数量多于较大的套娃

比如1 ,1,1,2,2,3,    其中1的数量>2的数量,那么此时多出的1就不能继续套娃了

③我们已经将所有娃都套好,那么原先还在套的娃此时就是不能再套的娃

最后输出不能再套的娃的数量就好了

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int N=2e5+10;
int s[N];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&s[i]);
		}
		sort(s,s+n);
		int num=1;//当前同尺寸套娃的数量
		int lnum=0;//先前同尺寸套娃的数量
		int cnt=0;
		for(int i=0;i<n-1;i++)
		{
			if(s[i]==s[i+1])//尺寸相同
			{
				num++;
			}
			else
			{
				if(s[i]+1!=s[i+1])//无法找到大一尺寸的套娃
				{
					cnt+=max(num,lnum);
					lnum=0;
					num=1;
				}
				else//可以找到大一尺寸
				{
					if(num<lnum)
					{
						cnt+=lnum-num;
					}
					lnum=num;
					num=1;
	
				}
			}
			
		}
		cnt+=max(num,lnum);
		cout<<cnt<<endl;
	}
	return 0;
}

E. Vlad and a Pair of Numbers

今天早上补的题目,感觉比前一题简单,当然可能是状态好些的原因

链接:Problem - E - Codeforces

题目:

 大意:

Vlad发现了两个正数a,b,其中a xor b=x    x=(a+b)/2

Vlad只记住了x的值,他将这个值告诉你,希望你可以找到a,b两数

有多种情况输出一种即可,没有输出-1

思路:考的是位运算的知识

如果x的二进制是1010

那么根据xor的规则,我们可以先草率的认为

a=1?1?

b=0?0?问号部分进行xor后结果是0,那么a,b对应位的?所代表的值是相同的

那么接下来我们只需要判断每位问号之后是1还是0即可

注意a+b=2x即可

代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int x;
		scanf("%d", &x);
		int x1 = x;
		int flag = 1;
		int a = 0, b = 0;
		int bit = 1, i = 0;
		while (bit <= x)
		{
			bit *= 2;
			i++;
		}
		i--;
		for (i; i >= 0; i--)
		{
			if ((x >> i & 1) == 0)
			{
				int p = pow(2, i);
				if (2 * p <= x1)
				{
					x1 -= 2 * p;
					a += p;
					b += p;
					if (x1 == 0)
					{
						break;
					}
				}
			}
		}
		if (x1)
		{
			printf("-1\n");
		}
		else
		{
			printf("%d %d\n", a + x, b);
		}
	}
	return 0;
}

 泪目啊,我刚刚快写完的草稿就这么没了

我又得重新写一遍了,

我应该记得保存的

太难受了

当你看到这个的时候,说明博主已经写两遍差不多的内容了

(咨询博主心理状态。。。。。)

所以可以给博主一些支持吗,比如

(疯狂暗示,几乎明示)

好了,谢谢你的观看,题解的话写起来还是蛮累的

最近快开学了,事情也多,题解短时间不会再更新了

  • 24
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 23
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幸麟同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值