牛客周赛 Round 40(A,B,C,D,E,F)

比赛链接

官方讲解

这场简单,没考什么算法,感觉有点水。D是个分组01背包,01背包的一点小拓展,没写过的可以看看,这个分类以及这个题目本身都是很板的。E感觉就是排名放高了导致没人敢写,本质上是个找规律然后分类讨论。F是个数学算期望的题,纯数学,连取模都没用就用的浮点数。


A 小红进地下城

思路:

签到,比较一下两个串是否相同即可。

code:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

string s1,s2;

int main(){
	cin>>s1>>s2;
	puts((s1==s2)?"Yes":"No");
	return 0;
}

B 小红打怪

思路:

找到小红的位置,然后往她面对的方向走,看有几个怪就行了,很签到。

code:

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=1005;

int n,m;
char mp[maxn][maxn];
int fx[]={-1,1,0,0},fy[]={0,0,-1,1};

int sx,sy,st;

int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>mp[i]+1;
		for(int j=1;j<=m;j++)
			if(mp[i][j]>='A' && mp[i][j]<='Z'){
				sx=i;
				sy=j;
				if(mp[i][j]=='W')st=0;
				else if(mp[i][j]=='S')st=1;
				else if(mp[i][j]=='A')st=2;
				else if(mp[i][j]=='D')st=3;
			}
	}
	
	int x=sx,y=sy,ans=0;
	do{
//		printf("(%d,%d)\n",x,y);
		ans+=(mp[x][y]=='*');
		x+=fx[st];
		y+=fy[st];
	}while(x>=1 && x<=n && y>=1 && y<=m);
	cout<<ans<<endl;
	return 0;
}

C 小红的排列构造

思路:

对第 i i i 个位置, a i a_i ai 一定是由 p i p_i pi q i q_i qi 给出,除此之外就没有什么限制了。

所以我们可以提出一个很简单的构造方法:先让 p p p 序列这个位置凑出 a i a_i ai,如果 p p p 序列没有这个数了(已经凑给其他位置了),那我们就让 q q q 序列去凑,如果都没有就无解。否则我们就得到了已经凑出了一部分的 p p p q q q。剩下的数没有限制,就依次补在空缺的位置上即可。

在一个序列剩余的数中查找还有没有某个数,并在给出这个数后把这个数删掉。我们可以用 s e t set set 来模拟这个过程,这题本质是个数据结构题。

code:

#include <iostream>
#include <cstdio>
#include <set>
using namespace std;
const int maxn=1e5+5;

int n,a[maxn];
int p[maxn],q[maxn];
set<int> s1,s2;

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		s1.insert(i);
		s2.insert(i);
	}
	for(int i=1;i<=n;i++){
		if(s1.find(a[i])!=s1.end()){
			p[i]=a[i];
			s1.erase(a[i]);
		}
		else if(s2.find(a[i])!=s2.end()){
			q[i]=a[i];
			s2.erase(a[i]);
		}
		else {
			cout<<-1;
			return 0;
		}
	}
	for(int i=1,x;i<=n;i++){
		if(p[i])x=p[i];
		else {
			x=*s1.begin();
			s1.erase(s1.begin());
		}
		cout<<x<<" \n"[i==n];
	}
	for(int i=1,x;i<=n;i++){
		if(q[i])x=q[i];
		else {
			x=*s2.begin();
			s2.erase(s2.begin());
		}
		cout<<x<<" \n"[i==n];
	}
	return 0;
}

D 小红升装备

思路:

换个思路,我们把一件武器看成是一组物品,这组物品包含:不购买它,购买它,购买它并升若干级的所有情况的武器,这样就变成了分组背包问题(有 N N N 组,每一组你至多选择一个物品(也可以不选),每个物品都有自己的体积和价值,现在给你一个容里为 M M M 的背包,让你用这个背包装物品,使得物品价值总和最大)

但是一把武器你有可能升很多级,导致这把武器可能有很多种情况,但是发现我们的钱是有限的,只有 300 300 300,每升一级还至少要花一块钱,因此我们最多只用升 300 300 300 级,多了也没用,反正也买不起。这样我们枚举一组之内的武器时,只枚举到能买得起的武器等级就行了。

剩下就是分组背包,很板。

code:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=305;

int n,x;
ll dp[maxn][maxn];

int main(){
	cin>>n>>x;
	for(int i=1,a1,c1,c2,a2,mx;i<=n;i++){
		cin>>a1>>c1>>c2>>a2>>mx;
		
		for(int j=0;j<=x;j++)dp[i][j]=dp[i-1][j];
		for(int j=0,cst,val;j<=mx && c1+j*c2<=x;j++){
			cst=c1+j*c2;
			val=a1+j*a2;
			
			for(int k=cst;k<=x;k++)
				dp[i][k]=max(dp[i][k],dp[i-1][k-cst]+val);
		}
	}
	
	ll ans=0;
	for(int i=0;i<=x;i++)
		ans=max(ans,dp[n][i]);
	cout<<ans;
	return 0;
}

E 小红的矩阵划分

思路:

注意题面上 n n n 为偶数的条件。

不难想到,如果两种类型的砖都能填满矩阵的话,我们肯定用砖的平均价值最大的类型来填,这样总数是确定的,总价值就是最大的。

不过并不一定两种类型的砖都能填满矩阵。由于 n n n 是偶数的条件, 2 ∗ 2 2*2 22 的砖一定可以填满,但是 L L L 型的不一定。

进一步研究发现, 当 n n n 6 6 6 的倍数的时候,一定可以用 L L L 型砖块填满。一种可行的策略如下:我们用两个 L L L 型砖块合成一个 2 ∗ 3 2*3 23 矩形形状的方块,它又可以组合成 6 ∗ 6 6*6 66 形状的方块,因此一定可以填满 n n n 6 6 6 的倍数的情况。

n n n 不为 6 6 6 的倍数的时候,我们可以参考上面的填充方式,把整个方阵拆分成一个最大的边长为 6 6 6 的倍数的方阵和两个长为 6 6 6 的倍数的矩形,以及一个小方阵。如下图(1为边长为 6 6 6 的倍数的方阵,23为长为 6 6 6 的倍数的矩形,4为小方阵)

在这里插入图片描述
我们还是用两个 L L L 型砖块合成一个 2 ∗ 3 2*3 23 矩形形状的砖块来对上面的图形进行填充。因为 n n n 为偶数,而且还不是 6 6 6 的倍数,所以 23 的宽,以及 4 的边长要么是 2 2 2,要么是 4 4 4。123很明显可以 2 ∗ 3 2*3 23 的矩形来填充。然后剩下一个 2 ∗ 2 2*2 22 或者 4 ∗ 4 4*4 44 的小方阵。

如果只用 L L L 型砖块来填充,一定会剩下一个格子。我们可以选择把一个 L L L 型砖块替换成 2 ∗ 2 2*2 22 型砖块来利用上这个空闲的格子,不过如果 L L L 型砖块价值很高的话,这里也可能不替换会更优。

所以可能出现的情况我们已经全部讨论出来了。总结如下:

  1. n n n 6 6 6 的倍数的时候,有两种选择:
    1. L L L 型砖块填充满。
    2. 2 ∗ 2 2*2 22 型砖块填充满。
  2. n n n 不为 6 6 6 的倍数的时候,有三种选择:
    1. L L L 型砖块填充满,这时剩一个空闲格子。
    2. 2 ∗ 2 2*2 22 型砖块填充满。
    3. L L L 型砖块填充满,再把一个 L L L 型砖块替换成 2 ∗ 2 2*2 22 型砖块。

code:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;

ll n,x,y;

int main(){
	cin>>n>>x>>y;
	if(n%3==0)cout<<max(n*n/3*x,n*n/4*y);
	else cout<<max(max(n*n/3*x,n*n/3*x-x+y),n*n/4*y);
	return 0;
} 

F 小红拿宝箱

思路:

发现只取两个宝箱,而且只有一次不取的机会。情况很小,所以我们可以直接人力分情况讨论,分别计算期望。

我们取宝箱只有三种情况,

  1. 不取,取,取
  2. 取,不取 取
  3. 取,取

当只取一个宝箱的时候,使不使用不取的权利的时机还是比较好确定的,就是高于期望就取,否则就不取,重新抽卡。但是还能取两个宝箱的时候就不好说了。所以我们第一步是否取宝箱先分类讨论。分成不取和取的情况,如果不取,那么后面就只能随便取两个宝箱了,不能不取。如果取,那么后面可以取,也可以不取然后再取。

这样情况讨论就变成了:

  1. 不取
    1. 取,取
    1. 不取 取

先讨论第一步取了,现在我们不使用不取宝箱的权利(或者说我们已经用完了不取宝箱的权利),随便取两个宝箱的话,期望计算:

n n n 个数中随便取两个的方法数为 C n 2 C_n^2 Cn2,每个取法平分取到的概率,因此一种取法的概率就是 1 C n 2 \dfrac1{C_n^2} Cn21。计算每个取法的价值比较困难,但是所有取法的价值总和可以算。我们计算期望的时候可以先把概率提公因式,然后先计算所有取法的价值总和。

如果我们钦定第一个数取了 a 1 a_1 a1,另一个数可以取剩下的 n − 1 n-1 n1 个数,这样第一个数取 a 1 a_1 a1 的所有取法之和就为 s u m 1 = ( n − 1 ) ∗ a 1 + ( a 2 + a 3 + ⋯ + a n ) sum_1=(n-1)*a_1+(a_2+a_3+\dots+a_n) sum1=(n1)a1+(a2+a3++an),假设所有数之和 t o t = ∑ i = 1 n a i tot=\sum_{i=1}^{n}a_i tot=i=1nai,那么式子可以写为: s u m 1 = ( n − 2 ) ∗ a 1 + t o t sum_1=(n-2)*a_1+tot sum1=(n2)a1+tot,同理其他数作为第一个数,所以可以得到所有取法的总和 s u m = ∑ i = 1 n s u m i = ( n − 2 ) ∗ ( a 1 + a 2 + ⋯ + a n ) + n ∗ t o t = 2 ∗ ( n − 1 ) ∗ t o t sum=\sum_{i=1}^n{sum_i}=(n-2)*(a_1+a_2+\dots+a_n)+n*tot=2*(n-1)*tot sum=i=1nsumi=(n2)(a1+a2++an)+ntot=2(n1)tot

因为我们计算的时候为了方便是钦定了取数顺序的,但是实际上取数是没有顺序的,因此我们要消除排序的影响,对一种可行的方案,我们由于有顺序,所以得到的所有方案相当于对原本的取数方案进行了一次全排列,一个方案分裂成了全排列个数个方案。比如这里的 a 1 , a 3 a_1,a_3 a1,a3 的一个取数方案就变成 a 1 , a 3 a_1,a_3 a1,a3 a 3 , a 1 a_3,a_1 a3,a1 一共 A 2 2 A_2^2 A22 个方案。因此我们对整个方案除以一个 A 2 2 = 2 A_2^2=2 A22=2 就可以消除掉排序的影响了。因此总的取法之和就是 s u m = ( n − 1 ) ∗ t o t sum=(n-1)*tot sum=(n1)tot。于是期望就是 ( n − 1 ) ∗ t o t C n 2 = t o t / n ∗ 2 \dfrac{(n-1)*tot}{C_n^2}=tot/n*2 Cn2(n1)tot=tot/n2


如果第一步取了,假设取了 a i a_i ai,现在随机取一个宝箱的期望就是 t o t − a i n − 1 \dfrac{tot-a_i}{n-1} n1totai。如果我们下一步取到的宝箱价值大于等于期望,就取它,否则如果小于期望,就重新随机抽取。为了快速算出有多少宝箱的价值大于期望,我们可以给宝箱价值从小到大排个序,然后二分查找第一个大于等于期望的位置,这样后面的宝箱价值都大于等于期望,前面的都小。

假设第 i d id id 个宝箱就是第一个大于等于期望的位置。那么后面 i d id id 个宝箱不重抽,每个的期望是 a j n − 1 ( j ≥ i d ) \dfrac{a_j}{n-1}\quad(j\ge id) n1aj(jid),前 i d − 1 id-1 id1 个宝箱要重新抽取,每个的期望就是 t o t − a i n − 1 n − 1 \dfrac{\frac{tot-a_i}{n-1}}{n-1} n1n1totai,不过需要注意的是,两种情况中有一个会包含进 a i a_i ai ,判断一下然后减去即可。期望之和就是 1 n − 1 ∗ ( ∑ j = i d n a j + ( i d − 1 ) ∗ t o t − a i n − 1 − ( i ≥ i d   ? a i : t o t − a i n − 1 )   ) \dfrac{1}{n-1}*(\sum_{j=id}^{n}a_j+(id-1)*\frac{tot-a_i}{n-1}-(i\ge id\,?a_i:\frac{tot-a_i}{n-1})\,) n11(j=idnaj+(id1)n1totai(iid?ai:n1totai))。这里 ∑ j = i d n a j \sum_{j=id}^{n}a_j j=idnaj 可以预处理后缀和来快速查询。


上面两个讨论分别代表了取与不取第一个数的后续的期望,我们两个总的期望取大的即可。

注意特判 n = 1 n=1 n=1 的情况。

code:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;

int n;
double a[maxn],suf[maxn],tot;

int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i],tot+=a[i];
	if(n==1)return cout<<tot,0;
	sort(a+1,a+n+1);
	for(int i=n;i>=1;i--)suf[i]=suf[i+1]+a[i];
	
	double s1=tot/n*2;//任取两个的期望 
	double ans=0;
	for(int i=1;i<=n;i++){
		double s2=(tot-a[i])/(n-1);//拿走ai后任取一个的期望 
		int id=lower_bound(a+1,a+n+1,s2)-a;
		double tmp=suf[id]+(id-1)*s2;//分子部分 
		if(a[i]>=s2)tmp-=a[i];
		else tmp-=s2;
		tmp/=n-1;
		ans+=max(s1,tmp+a[i]);
	}
	printf("%.11lf\n",ans/n);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/567124.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

aardio - 【库】图片转字符画

库文件及例程下载&#xff1a;https://aardio.online/thread-261.htm

PyCharm 中的特殊标记

再使用 PyCharm 开发 Python 项目的时候&#xff0c;经常会有一些特殊的标记&#xff0c;有些是编辑器提示的代码规范&#xff0c;有些则为了方便查找而自定义的标记。 我在之前写过一些关于异常捕获的文章&#xff1a;Python3 PyCharm 捕获异常报 Too broad exception clause…

苹果手机怎么换行?分享3个换行小窍门

“晕&#xff01;第一次使用苹果手机&#xff0c;还有很多功能不懂&#xff0c;比如我在手机上打字怎么换行&#xff1f;我在键盘上找了很久&#xff0c;还是没有找到。” “为什么在发消息用苹果手机自带键盘没有换行键&#xff1f;我该怎么快速换行&#xff1f;求方法&#…

重学java 19.面向对象 继承 上

走不出的那段阴霾&#xff0c;很多时候只不过是&#xff0c;我们把它当成了唯一 —— 24.4.22 面向对象整体知识导向&#xff1a; 知识梳理&#xff1a; 1.知道继承的好处 2.会使用继承 3.继承之后成员变量和成员方法的访问特点 4.方法的重写&#xff0c;知道方法重写的使用场景…

sprinboot+人大金仓配置

1. .yml 配置 spring:datasource:type: com.alibaba.druid.pool.DruidDataSource#driverClassName: dm.jdbc.driver.DmDriver## todo 人大金仓driverClassName: com.kingbase8.Driverdruid:## todo 人大金仓master:url: jdbc:kingbase8://111.111.111.111:54321/dbname?cu…

helpdesk桌面运维常见问题解决

helpdesk是一套帮助IT团队管理IT工单生命周期、自动化日常工作、优化工作流程的软件或软件集合&#xff0c;它可以帮助IT团队提高生产力、降低成本、改善服务水平和客户体验。 在现代企业中&#xff0c;helpdesk桌面运维是一项至关重要的工作&#xff0c;helpdesk团队负责处理员…

虚拟信用卡是什么,可以用来开亚马逊店铺吗?

虚拟信用卡是什么&#xff1f; 虚拟信用卡就是一组由银行随机生成的数字的虚拟卡&#xff0c;使用起来方便快捷&#xff0c;对于个人而言保守自己的隐私&#xff0c;并且下卡快&#xff0c;即开即用 可以用来开亚马逊店铺吗&#xff1f; 可以&#xff0c;因为市场的需求很多…

面试官:在原生input上面使用v-model和组件上面使用有什么区别?

前言 还是上一篇面试官&#xff1a;来说说vue3是怎么处理内置的v-for、v-model等指令&#xff1f; 文章的那个粉丝&#xff0c;面试官接着问了他另外一个v-model的问题。 面试官&#xff1a;vue3的v-model都用过吧&#xff0c;来讲讲。 粉丝&#xff1a;v-model其实就是一个语…

储能展-CBTC-2024上海储能技术展会共话储能高质量发展

2024-CBTC上海国际储能技术展会 展会时间&#xff1a;7月24-26日 展会地址&#xff1a;上海&#xff08;虹桥&#xff09;国家会展中心 主办单位&#xff1a;湖南省电池产业协会/ 中国设备管理协会 /沪粤储能产业联盟/ 深圳国际投融资商会 国际氢能投融资与发展联…

Qt Debug模式下应用程序输出界面乱码【已解决】

Qt Debug模式下应用程序输出乱码 一、问题描述二、解决方法三、相关测试 一、问题描述 源码为utf-8编码. Qt Creator在Debug模式下运行程序&#xff0c;下方应用程序输出界面显示乱码. 但正常运行无乱码&#xff1a; 二、解决方法 尝试修改文件编码、执行编码无果… 可参考…

Python从0到100(十四):高级函数及函数使用进阶

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

Day11-Java进阶-HashSet集合LinkedHashSet-Collection工具类Map集合

1. HashSet集合 HashSet-JDK8版本及以后-面试常问 2. LinkedHashSet-Collection工具类 2.1 LinkedHashSet 2.2 Collection工具类 3. Map集合 3.1 Map接口介绍 3.2 Map 集合的遍历方式 3.2.1 三种方式介绍 package com.itheima.map;import java.util.HashMap; import java.ut…

【C++类和对象】日期类的实现

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

【MATLAB源码-第64期】matlab基于DWA算法的机器人局部路径规划包含动态障碍物和静态障碍物。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 动态窗口法&#xff08;Dynamic Window Approach&#xff0c;DWA&#xff09;是一种局部路径规划算法&#xff0c;常用于移动机器人的导航和避障。这种方法能够考虑机器人的动态约束&#xff0c;帮助机器人在复杂环境中安全、…

PCB上有哪些元素

过孔&#xff1a;是用来切换层的 丝印&#xff1a;就是标记&#xff08;白色的线或者符号&#xff09; 焊盘&#xff1a;焊接元器件&#xff0c;相当于线头&#xff0c;连接各个元件 通孔埋孔盲孔&#xff0c;都是用来换层&#xff0c;内部没有桐&#xff0c;是用来固定的 线路…

C++:基础语法

一、命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c; 以避免命名冲突或名字污染&#xff0c;n…

uniapp微信小程序(商城项目)

最近&#xff0c;闲来无事&#xff0c;打算学一下uniapp小程序 于是在跟着某站上学着做了一个小程序&#xff0c;主要是为了学uniapp和vue。某站黑马优购 完成的功能主要有&#xff1a;首页、搜索、分类和购物车。 有人问了为什么没有登录、和添加订单呢&#xff1f;问的很好…

2.4 Web容器配置:Tomcat

2.4 Web容器配置 2.4.1Tomcat配置1.常规配置2. HTTPS配置 *********** 2.4.1Tomcat配置 1.常规配置 在SpringBoot项目中&#xff0c;可以内置Tomcat、Jetly、Undertow、Netty等容器。 当开发者添加了spring-boot-starter-web依赖之后&#xff0c;默认会使用Tomcat作为Web容器…

【Linux学习】初始冯诺漫体系结构

文章目录 认识冯诺依曼系统 认识冯诺依曼系统 什么是冯诺依曼体系结构&#xff1f; 冯诺依曼体系结构是一种将程序指令和数据以二进制形式存放在主存储器中&#xff0c;由中央处理器统一控制和执行的计算机系统结构。冯诺依曼体系结构实现了程序的可编程性和硬件与软件的分离&…
最新文章