首页 > 其他分享 > 罗勇军老师每日一题系列

罗勇军老师每日一题系列

时间:2023-08-26 20:34:57浏览次数:31  
标签:系列 int 老师 cin long mp Answer include 罗勇军

罗勇军老师每日一题系列

罗老师有专门的题解,这里只是个人的做题总结。 罗老师的QQ群,930175362

罗老师博客

1.最小区间

有n头奶牛,奶牛有位置\(P[i]\)和类别\(T[i]\)两种属性,求能够包含所有类别的奶牛的最小区间的长度。

\(1 <= n <= 5e4 , P[i] , T[i] <= 1e9\)

题解

二分答案。

二分区间长度,不断右移左端点的时候,右端点不会左移。

再将种类离散化之后用一个桶维护,就可以\(O(n)\)判断答案的正确与否。

#include<algorithm>
#include<iostream>
using namespace std;
const int N = 5e4+10;
int n , m;
int B[N] , t[N];

struct cow{
	int pos , kind;
	bool operator < (const cow &B) const { return pos < B.pos; }
}A[N];

bool Check(int len)
{
	/*
		判断长度为len的区间是否可行。
		l不断右移的过程中,r不会左移,保证了复杂度是O(n)的。
		关于当前区间的种类数,可以用桶来维护,在出现次数0、1变换时统计。
	*/
	int r = 0 , num = 0 , F = 0;
	for(int l = 1 ; l <= n ; ++l)
	{
		while(r + 1 <= n && A[r + 1].pos - A[l].pos <= len)
		{
			r++;
			if(t[A[r].kind] == 0) num++;
			t[A[r].kind]++;
		}
		if(num >= m) F = 1;
		
		t[A[l].kind]--;
		if(t[A[l].kind] == 0) num--;
	}
	return F;
}

int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int l , r , mid;
	cin >> n;
	for(int i = 1 ; i <= n ; ++i)
	{
		cin >> A[i].pos >> A[i].kind;
		B[i] = A[i].kind;
	}

	sort(B + 1 , B + 1 + n);
	m = unique(B + 1 , B + 1 + n) - B - 1;
	sort(A + 1 , A + 1 + n);
	for(int i = 1 ; i <= n ; ++i) // 离散化种类数
		A[i].kind = lower_bound(B + 1 , B + 1 + m , A[i].kind) - B;

	l = 1; r = 1e9;
	while(l < r)
	{
		mid = (l + r) >> 1;
		if(Check(mid)) r = mid; else l = mid + 1;
	}
	cout << l << '\n';
	return 0;
}

2.单位转换

给定 n 组单位换算关系式,q 组询问,每次将某个单位转换成另一个单位。
单位换算关系式:1 =

表示左边的 1 个单位的 等价于 个单位的
询问格式: to

询问 个单位的 等价于多少个单位的

\(1 <= n <= 100 , 1 <= 10000 , <value>为浮点数属于[0.001 , 1000],小数点后最多9位数字\)

题解

这里我用了类似Floyd的做法,来求出这些单位之间两两转化的比例。

可能是精度问题,导致出了几次WA,所以使用了long double。

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

unordered_map<string , int> mp;
long double dis[105][105];

int main()
{
	int n , m , tot;
	long double val;
	string str , u , v;

	cin >> n >> m; tot = 0;
	for(int i = 1 ; i <= n ; ++i)
	{
		cin >> val;
		cin >> u;
		cin >> str;
		cin >> val;
		cin >> v;
		if(!mp.count(u)) mp[u] = ++tot;
		if(!mp.count(v)) mp[v] = ++tot;
		dis[mp[u]][mp[v]] = val;
		dis[mp[v]][mp[u]] = 1.0 / val;
	}
		
	for(int i = 1 ; i <= tot ; ++i) dis[i][i] = 1.0;
		
	for(int k = 1 ; k <= tot ; ++k)
		for(int i = 1 ; i <= tot ; ++i)
			for(int j = 1 ; j <= tot ; ++j) // 如果通过了60~80,可以试着加上类似如下的判断
											// 本人就是加上这个之后才A掉的。
				if(dis[i][j] == 0 && dis[i][k] > 0 && dis[k][j] > 0)
					dis[i][j] = dis[i][k] * dis[k][j];
	
	for(int i = 1 ; i <= m ; ++i)
	{
		cin >> val;
		cin >> u;
		cin >> str;
		cin >> v;
		if(mp.count(u) && mp.count(v) && dis[mp[u]][mp[v]] > 0)
			cout << fixed << setprecision(8) << dis[mp[u]][mp[v]] * val << '\n';
		else
			cout << "impossible" << '\n';
	}
	return 0;
}

3.凑二十四

给n个数字,在n-1个间隔中插入\(+、-、*\)三种运算符,请问有多少种方案可以使得式子的结果为24.

计算时按照正常优先级,即先乘后加减。

\(2 <= n <= 10\)

题解

数据范围很小,可以直接暴力搜索,进行\(3^{10}\)枚举。

这里分享一下计算这个式子的写法。

首先,计算式子中的乘法。

​ 用一个数组(栈)存储,从左往右扫描,如果没有碰到乘法操作则将对应的数字放进去,这个数字前面是加号则就是正的,是减号就认为是负的。

​ 如果碰到了乘法操作就拿出最后一个放入的元素和它相乘再将结果放回数组。

​ 最后将整个数组中剩余的元素累加即可。

这里面因为 \(- (a*b)\) 和 \((-a) * b\)的效果是一样的,所以这些数字就可以直接由它们前面的符号确定正负。

然后遇到乘法操作就 就地完成 然后将结果放进数组。

#include<iostream>
using namespace std;
int n , Answer;
int A[20] , B[20];
long long Stack[20];

int Check()
{
	// 1 +
	// 2 -
	// 3 *
	int top = 0;
	long long res = 0;
	Stack[top = 1] = A[1];
	for(int i = 2 ; i <= n ; ++i)
	{
		if(B[i-1] == 3) // 遇到了乘法
		{
			while(i <= n && B[i-1] == 3) Stack[top] *= A[i] , i++;
			i--;
		}
		else
		if(B[i-1] == 2) // 前是减号
			Stack[++top] = -A[i];
		else            // 前是加号
			Stack[++top] = A[i];
	}
	for(int i = 1 ; i <= top ; ++i) res += Stack[i];
	return res == 24;
}

void dfs(int x)
{
	if(x == n)
	{
		Answer += Check();
		return ;
	}
	for(int i = 1 ; i <= 3 ; ++i)
		B[x] = i , dfs(x + 1) , B[x] = 0;
}

int main()
{
	cin >> n;
	for(int i = 1 ; i <= n ; ++i) cin >> A[i];
	dfs(1);
	cout << Answer << '\n';
	return 0;
}

4. 最小公倍数

给一个数字n,问是否存在一个区间,这个区间所有数字的最小公倍数是n。(区间长度大于1)

若有多解,按照左端点为第一关键字,右端点为第二关键字,取小的。

\(1 <= n <= 1e18\)

题解

从大方向上看,一个区间的最小公倍数和这个区间所有数字的乘积差不多。

所以长度大于等于2的区间的枚举范围是\({\sqrt {n}} ^ 2 = 1e18?\)

长度大于等于3的区间的枚举范围就是\({\sqrt[3]{n}} ^ 2 = 1e12 ?\)

而长度为2的区间的最小公倍数就是两个数字相乘。(相邻两个数字的最小公倍数就是这两个数字相乘)

所以可以枚举长度大于等于3的区间计算其最小公倍数,并存储器起来,查询时再输出。

因为lcm增长很快,所以上面的式子其实是远远不满的。

#pragma GCC optimize(2) // 这个O(2)没开的时候TLE了
#include<unordered_map>
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const long long inf = 1e18;
unordered_map<long long , pair<int,int> > mp;

long long gcd(long long a , long long b) { return a ? gcd(b % a , a) : b; }

void Init()
{
	register int i , j;
	long long res , tmp;
	for(i = 1 ; i <= 2e6; ++i) // 左端点大于1e6的长度大于等于3的区间 也有可能lcm <= 1e18
	{
		res = 1ll * i * (i + 1);
		for(j = i + 2 ;  ; ++j)
		{
			tmp = __gcd(res , 1ll * j);
			if(res / tmp > inf / j) break;
			
			res = res / tmp * j;
			
			if(!mp.count(res)) mp[res] = make_pair(i , j);
		}
	}
}

int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int T , t; 
	long long n;
	pair<int,int> Answer;
	Init();
	
	scanf("%d" , &T);
	while(T--)
	{
		scanf("%lld" , &n); t = sqrt(n); Answer = make_pair(1e9 , 1e9);
		
		if(mp.count(n)) // 有区间大于等于3的解
			Answer = min(Answer , mp[n]);
		if(1ll * t * (t + 1) == n) // 有区间长为2的解
			Answer = min(Answer , make_pair(t , t + 1));
		
		if(Answer.first != 1e9) // 有解
			printf("%d %d\n" , Answer.first , Answer.second);
		else
			printf("-1\n");
	}
	return 0;
}

标签:系列,int,老师,cin,long,mp,Answer,include,罗勇军
From: https://www.cnblogs.com/sybs5968QAQ/p/17659403.html

相关文章

  • hdu:不容易系列之(3)—— LELE的RPG难题
    ProblemDescription人称“AC女之杀手”的超级偶像LELE最近忽然玩起了深沉,这可急坏了众多“Cole”(LELE的粉丝,即”可乐”),经过多方打探,某资深Cole终于知道了原因,原来,LELE最近研究起了著名的RPG难题:有排成一行的n个方格,用红(Red)、粉(Pink)、绿(Green)三色涂每个格子,每格涂一色,要......
  • 【Sword系列】第七届全国残疾人职业技能大赛样题-网络安全-古典密码
    (文章目录)前言古典密码是指使用传统的替换或移位方式对明文进行加密,例如凯撒密码、栅栏密码等。在这种加密方式中,加密密钥通常是公开的,因此易被破解。现代密码学基本上已经放弃了古典密码的加密方式,而采用更加高级的数学算法来保证加密的安全性。ASCII是一种字符编码标准,它规......
  • 玩转 PI 系列-看起来像服务器的 ARM 开发板矩阵-Firefly Cluster Server
    前言基于我个人的工作内容和兴趣,想要在家里搞一套服务器集群,用于容器/K8s等方案的测试验证。考虑过使用二手服务器,比如DellR730,还搞了一套配置清单,如下:DellR7303.5尺寸规格硬盘CPU:2686v4*2内存:16g*8存储:480Gintelssd系统盘+6tsas希捷*2个数据盘RAID卡:h73......
  • 玩转 PI 系列-看起来像服务器的 ARM 开发板矩阵-Firefly Cluster Server
    前言基于我个人的工作内容和兴趣,想要在家里搞一套服务器集群,用于容器/K8s等方案的测试验证。考虑过使用二手服务器,比如DellR730,还搞了一套配置清单,如下:DellR7303.5尺寸规格硬盘CPU:2686v4*2内存:16g*8存储:480Gintelssd系统盘+6tsas希捷*2个数据盘RAID卡:h7......
  • 学信息系统项目管理师第4版系列01_导读
    2023年对于信息系统项目管理师(以下简称“高项”)的考生来说真是命运多舛的一年,上半年改大纲换教材,下半年改机考换考法,真是一言难尽啊。不过,“天要下雨,娘要嫁人”,该考试拿证还是一样要考试拿证,废话也不要多说了。1.导读图基本上应该是按照图示的章节进行更新。距离11月4日考试......
  • 从零做软件开发项目系列之五——系统开发过程
    前言在软件项目的设计开发过程中,除了前期的用户需求调研确认,系统设计、数据库设计等工作之外,还有一些重要的工作需要考虑,比如软件开发模式,如何制定开发计划,如何协调开发人员开展开发工作等。本文将这几项内容与大家进行分享交流。1软件开发模式(模型)我们在项目中,根据具体情况,会......
  • 【Maven技术专题】「实战开发系列」盘点Maven项目中打包需要注意到的那点事儿
    Maven是什么Maven是一个流行的Java构建工具,它提供了许多插件来帮助开发人员自动化构建和部署Java应用程序。其中一个重要的插件是Maven打包插件,它可以将Java项目打包成可执行的JAR或WAR文件。在本文中,我们将深入探讨Maven打包插件的技术细节和使用方法。Maven打包插件的作用Maven打......
  • Exceptionless系列:简介和部署(Windows、Linux、Docker)
    目录一、简介二、版本三、运行说明1、Exceptionless2、Elasticsearch3、Exceptionless.UI四、打包Exceptionless.UI五、window部署1.Elasticsearch2.Exceptionless六、Docker部署一、简介Exceptionless为您提供了跟踪错误、日志和事件的工具,同时指导您找到可行的解决方案。首先......
  • 赵老师 计数原理 课程笔记
    计数原理分类加法计数原理与分步乘法计数原理分类加法计数原理引例题干用一个大写的英文字母或一个阿拉伯数字给教室里的一个座位编号,总共能编出多少种不同的号码?解决因为英文字母共有\(26\)个,阿拉伯数字共有\(10\)个,所以总共可以编出\(26+10=36\)种不同的号......
  • 模拟集成电路设计系列博客——1.2.2 共漏放大器(源极跟随器)
    1.2.2共漏放大器(源极跟随器)另一个电流镜的常见应用时为源极跟随器提供偏置电流,在下图的例子中,\(Q_1\)为源极跟随器,\(Q_2\)为给\(Q_1\)提供偏置电流的有源负载,这个结构一般用于电压缓冲器,因此也被称作源极跟随器。因为输入和输出节点分别在栅极和源极,漏极作为小信号地,这个结构同......