春季测试 2023 我的题解

T1 涂色游戏

这道题目还是比较简单的
容易发现,位于 ( x i , y i ) (x_i,y_i) (xi,yi) 的格子的颜色只取决于 ​ x i x_i xi 行与 y i y_i yi 列的颜色。

这时候可以想到开两个数组,分别存储列与行的绘画信息,然后发现前后的互相覆盖可以通过存储绘画顺序来得出。

考虑 L i L_i Li 表示第 i i i 行最后一次被染成什么颜色, U i U_i Ui 表示第 i i i 列最后一次被染成什么颜色,同时记录下这些操作的时间先后顺序。
那么对于最终的格子 ( i , j ) (i,j) (i,j) ,它的颜色就是 L i L_i Li U j U_j Uj 中更晚的一个,简单判断一下然后输出即可。

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

int read(){
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0') {
		if(ch=='-') f=-1;
		ch=getchar(); 
	}
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*f;
}

const int N = 1e5 + 5;
int n, m, q;
pair<int, int> L[N], U[N];

void Init() {
	for (int i = 1; i <= n; ++i) {
		L[i] = make_pair(0, 0);
	}
	
	for (int i = 1; i <= m; ++i) {
		U[i] = make_pair(0, 0);
	}
}
int main() {
	int T=read();
	while (T--){
		n=read(),m=read(),q=read();
		Init();
		for (int i = 1; i <= q; i++) {
			int opt=read(),x=read(),y=read(); 
			if (opt == 0) {
				L[x] = make_pair(y, i);
			} else {
				U[x] = make_pair(y, i);
			}
		}
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				if (L[i].second > U[j].second) {
					cout << L[i].first << ' ';
				} else {
					cout << U[j].first << ' ';
				}
			}
			puts("");
		}
	}
	return 0;
}

T2 幂次

这道题如果在考场上不认真分析也就会做不出来

首先就是骗分:
发现 k = 1 k=1 k=1 ,就直接输出 n n n 就行了

考虑一个比较简单的暴力, 枚举 [ 1 , n ] [1, n] [1,n] 中的每个数作为 a a a , 然后枚举 b b b , 直到 a b ≥ n a^{b} \geq n abn 就让 a + + \mathrm{a}++ a++ 然后重新枚举 b b b , 每个没出现过的数使 a n s + + ans ++ ans++

先不考虑去重, 我们来思考如何优化这个暴力。注意到当我们枚举的 b b b 增加时, 使 a b a^{b} ab 首次 ≥ n \geq n n a a a 会越来越小,由此我们可以对每个 b b b 二分求出一个 a a a 的上界,此时 a a a 的上界是 n n n 次根号级别的。

因为 2 60 ≥ 1 0 18 2^{60} \geq 10^{18} 2601018 , 所以 b b b 实际的范围并不大。对于 k ≥ 3 k \geq 3 k3 的情况我们都可以枚举 b b b 求出 a a a 的上界然后直接暴力求所有快速幂做了。剩下的情况中, k = 1 k=1 k=1 时答案显然为 n n n , 那么 k = 2 k=2 k=2 时如何做?

此时回来考虑去重, 所以求完快速幂后再枚举每个 ≤ b \leq b b x x x 作为新的指数。然后对当前求得的 a b a^{b} ab x x x 次方根, 看是否有正整数解, 就可以判定是否与之前计算过的重复了。

此时 k = 2 k=2 k=2 的情况就迎刃而解了,我们直接令初始 a n s 为 n ans 为 \sqrt{n} ansn 即可。
还要注意 a a a 1 1 1 的情况, 在初始答案上略作修改就行。
时间复杂度比较抽象, 我不会表示, 交了反正能过。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int read() {
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0') {
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*f;
}
using namespace std;
using i64 = long long;
i64 n, a[100010];
int k;
long double Qpow(int x, int y) {
	long double res = 1, base = x;
	for (; y; y >>= 1, base *= base) {
		if (y & 1) {
			res *= base;
		}
	}
	return res;
}
int GetRoot(int x, int y) {
	int l = 1, r = x;
	while (l <= r) {
		int mid = (l + r) >> 1;

		if (Qpow(mid, y) > x) r = mid - 1;
		else l = mid + 1;
	}
	return r;
}
signed main() {
	n=read(),k=read();
	i64 res = 1;
	int lim = 0;
	for (int i = k; ; ++i) {
		int v = GetRoot(n, i);
		lim = i;
		if (v <= 1) break;
		a[i] = v - 1;
	}
	for (int i = lim - 1; i >= k; --i) {
		for (int j = i + i; j <= lim; j += i) {
			a[i] -= a[j];
		}
	}
	for (int i = k; i < lim; ++i) {
		res += a[i];
	}
	cout << res << '\n';
	return 0;
}

T3

很显然的一个结论就是连接的路径一定不能相交。证明考虑相交的时候交换两个顶点的顺序一定更优。
假设已经连接的点的集合为 S S S ,那么 S S S 一定在凸多边形上是连续的,因此有一个很显然的 D P DP DP: 设 f ( i , j , 0 / 1 ) f(i, j, 0 / 1) f(i,j,0/1) 表示从 k k k 逆时针转选了 i i i 个,顺时针转选了 j j j 个,当前在左侧 / / / 右侧。转移很明显(用 L ( x ) L(x) L(x) 表示 k k k 逆时针开始的第 x x x 个, R ( x ) R(x) R(x) 表示顺时针的第 x x x 个):

f ( i , j , 0 ) ← f ( i − 1 , j , 0 ) + dis ⁡ ( L ( i − 1 ) , L ( i ) ) f ( i , j , 0 ) ← f ( i − 1 , j , 1 ) + dis ⁡ ( R ( j ) , L ( i ) ) f ( i , j , 1 ) ← f ( i , j − 1 , 0 ) + dis ⁡ ( L ( i ) , R ( j ) ) f ( i , j , 1 ) ← f ( i , j − 1 , 1 ) + dis ⁡ ( R ( j − 1 ) , R ( j ) ) \begin{array}{l} f(i, j, 0) \leftarrow f(i-1, j, 0)+\operatorname{dis}(L(i-1), L(i)) \\ f(i, j, 0) \leftarrow f(i-1, j, 1)+\operatorname{dis}(R(j), L(i)) \\ f(i, j, 1) \leftarrow f(i, j-1,0)+\operatorname{dis}(L(i), R(j)) \\ f(i, j, 1) \leftarrow f(i, j-1,1)+\operatorname{dis}(R(j-1), R(j)) \end{array} f(i,j,0)f(i1,j,0)+dis(L(i1),L(i))f(i,j,0)f(i1,j,1)+dis(R(j),L(i))f(i,j,1)f(i,j1,0)+dis(L(i),R(j))f(i,j,1)f(i,j1,1)+dis(R(j1),R(j))

最终答案就是 min ⁡ 0 ≤ i < n min ⁡ ( f ( i , n − i − 1 , 0 ) , f ( i , n − i − 1 , 1 ) ) \min _{0 \leq i<n} \min (f(i, n-i-1,0), f(i, n-i-1,1)) min0i<nmin(f(i,ni1,0),f(i,ni1,1))
题目要求输出方案,那么就在转移的过程中再记录一个 from ⁡ ( i , j , 0 / 1 ) \operatorname{from}(i, j, 0 / 1) from(i,j,0/1) 表示当前状态是又哪一个转移过来的,最后遍历输出即可。
贴一个证明过程
在这里插入图片描述

#include<bits/stdc++.h>
#define int long long
int read(){
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0') {
		if(ch=='-') f=-1;
		ch=getchar(); 
	}
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*f;
}
using namespace std;
const int N=1e3+10;
struct node {
	double x,y;
} a[N];
struct point {
	int l,r,x;
} fa[N][N][2];
int n,m,T;
double f[N][N][2],ans;
bool chmin(double& x,double y) {
	if(x>y) x=y;
	return (x==y);
}
int ex(int x) {
	if(x<=0) x+=n;
	if(x>n) x-=n;
	return x;
}
double dist(int x,int y) {
	return sqrt((a[x].x-a[y].x)*(a[x].x-a[y].x)+(a[x].y-a[y].y)*(a[x].y-a[y].y));
}
signed main() {
	n=read();
	for(int i=1; i<=n; ++i) cin>>a[i].x>>a[i].y;
	double maxn=-1e9;
	for(register int i=1; i<=n; ++i) {
		if(a[i].y>maxn) {
			maxn=a[i].y;
			m=i;
		}
	}
	for(register int i=0; i<=n; ++i) for(register int j=0; j<=n; ++j) f[i][j][0]=f[i][j][1]=1e18;
	f[0][0][0]=f[0][0][1]=0;
	for(register int len=1; len<n; ++len) {
		for(register int l=0; l<=len; ++l) {
			int r=len-l;
			if(l&&chmin(f[l][r][0],f[l-1][r][0]+dist(ex(m+l),ex(m+l-1)))) fa[l][r][0]=(point) {
				l-1,r,0
			};
			if(l&&chmin(f[l][r][0],f[l-1][r][1]+dist(ex(m+l),ex(m-r))))   fa[l][r][0]=(point) {
				l-1,r,1
			};
			if(r&&chmin(f[l][r][1],f[l][r-1][0]+dist(ex(m-r),ex(m+l))))   fa[l][r][1]=(point) {
				l,r-1,0
			};
			if(r&&chmin(f[l][r][1],f[l][r-1][1]+dist(ex(m-r),ex(m-r+1)))) fa[l][r][1]=(point) {
				l,r-1,1
			};
		}
	}
	ans=1e18;
	point jump;
	for(register int i=0; i<n; ++i) {
		if(f[i][n-i-1][0]<ans) {
			ans=f[i][n-i-1][0];
			jump=(point) {
				i,n-i-1,0
			};
		}
		if(f[i][n-i-1][1]<ans) {
			ans=f[i][n-i-1][1];
			jump=(point) {
				i,n-i-1,1
			};
		}
	}
	printf("%lld ",m);
	stack<int> s;
	while(jump.l>0||jump.r>0) {
		s.push((jump.x==0?ex(m+jump.l):ex(m-jump.r)));
		jump=fa[jump.l][jump.r][jump.x];
	}
	while(!s.empty()) printf("%lld ",s.top()),s.pop();
	return 0;
}

T4

这道题骗分要随机化,但是随机化我不会,老师只说了random,所以就先学随机种子
考场随机需谨慎,提防爆零两行泪。
附一个链接 https://blog.csdn.net/yeepom/article/details/8625184
还有一个 :https://blog.csdn.net/xiyangxiaoguo/article/details/104847770
说实在的,考试时打死我我也想不上来用随机数乱搞,就算想到了,也照样不知道怎么用,分析实际情况,我选择写特殊性性质

对于 k = 1 k=1 k=1 的情况 就是求极差
对于 k = 2 k=2 k=2 的情况
考虑将小的数放上面,大的数放下面。
思考一下这样为什么是对的?考虑全局最小值和全局最大值所在的行,显然放在两行不劣于放在同一行,设最小值放上面,最大值放下面,那么要想让上面的数尽量小,下面的数尽量大,就是上面的方法。
下面给出部分分的代码

		if(k==1){
			int minn=1e9,maxn=-1e9;
			for(int i=1;i<=n;i++){
				minn=min(minn,a[1][i]);
				maxn=max(maxn,a[1][i]);
			}
			printf("%d\n",maxn-minn);
		}

k = 1 , 10 p t s k=1,10pts k=1,10pts

FOR(i,0,k-1) FOR(j,1,n){
			b[i][j]=rd;
			if(b[i][j]>mxx) mxx=b[i][j],mxl=j,mxa=i;
			if(b[i][j]<mnn) mnn=b[i][j],mnl=j,mna=i;
		}
		ans=max(mxx-b[mna^1][mnl],b[mxa^1][mxl]-mnn);
		FOR(j,1,n){
			if(j==mxl||j==mnl) continue;
			int tmp1=max(mxx-b[0][j],b[1][j]-mnn);
			int tmp2=max(mxx-b[1][j],b[0][j]-mnn);
			ans=max(ans,min(tmp1,tmp2));
		}
		printf("%d\n",ans);

k = 2 , 20 p t s k=2,20pts k=2,20pts
其实再加上暴力搜索就又能拿 10 p t s 10pts 10pts
CCF如果数据水,就又能操过去几个点

int res;
void dfs(int x){
        if(x>n){
                int tmp=0;
                FOR(i,0,k-1){
                        int mx=0,mn=INF;
                        FOR(j,1,n) mx=max(mx,p[i][j]),mn=min(mn,p[i][j]);
                        tmp=max(tmp,mx-mn);
                }
                res=min(res,tmp);
                return;
        }
        FOR(j,0,k-1){
                FOR(i,0,k-1) p[(j+i)%k][x]=a[i][x];
                dfs(x+1);
        }
}
void solve3(){
        while(T--){
                n=rd;res=INF;
                FOR(i,0,k-1) FOR(j,1,n) a[i][j]=rd;
                dfs(1);printf("%d\n",res);
        }
}

本题拿捏分数: 40 p t s 40pts 40pts

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

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

相关文章

Kali Linux 新工具推荐: Sploitscan

在 2024.2 版本 Kali Linux 增加了一个新攻击工具: Sploitscan 1.简介: Sploitscan 能够发现操作系统和应用程序中的安全漏洞。 2.特点: 简单的命令行界面 扫描多个操作系统和应用程序 检测多种漏洞 提供详细信息 可定制性强 3.示例: 2024.2 及以后的版本 Kali Linux…

【JAVA 笔记】09 ch06_arrays_sort_and_search

第6章 数组、排序和查找 数组介绍 数组的使用 使用方式1-动态初始化数组的定义 使用方式2-动态初始化 使用方式3-静态初始化 数组使用注意事项和细节 数组应用案例 数组赋值机制 数组拷贝 数组添加/扩容 多维数组 二维数组 动态初始化1 动态初始化2 静态初始化 二维数组的应用案…

C语言实现归并排序

#include <stdio.h> #include <stdlib.h> #include<time.h> #include<string.h> #define N 7 // 定义元素类型为整型 typedef int ElemType; // 定义静态表结构体 typedef struct{ ElemType *elem; // 动态分配的数组指针 int TableL…

第十八章 Vue组件样式范围配置之scoped

目录 一、引言 二、案例演示 2.1. 工程结构图 2.2. 核心代码 2.2.1. main.js 2.2.2. App.vue 2.2.3. BaseOne.vue 2.2.4. BaseTwo.vue 2.3. 运行效果 2.4. 调整代码 2.4.1. BaseTwo.vue 2.4.2. 运行效果 三、scoped原理 一、引言 前面的几个章节在介绍组件的时…

Linux 中,flock 对文件加锁

在Linux中&#xff0c;flock是一个用于对文件加锁的实用程序&#xff0c;它可以帮助协调多个进程对同一个文件的访问&#xff0c;避免出现数据不一致或冲突等问题。以下是对flock的详细介绍&#xff1a; 基本原理 flock通过在文件上设置锁来控制多个进程对该文件的并发访问。…

stm32入门教程-- DMA数据转运

目录 简介 原理 实验示例 1、DMA数据转运 实现代码 实验效果 原理 实验示例 1、DMA数据转运 接线图 存储器映像 我们在开始代码之前&#xff0c;可以看下我们定义的数据&#xff0c;到底是不是真的存储在了这个相应的地址区间里&#xff0c;我们看代码&#xff1a; …

SELS-SSL/TLS

一、了解公钥加密&#xff08;非对称加密&#xff09; 非对称加密中&#xff0c;用于加密数据的密钥与用于解密数据的密钥不同。私钥仅所有者知晓&#xff0c;而公钥则可自由分发。发送方使用接收方的公钥对数据进行加密&#xff0c;数据仅能使用相应的私钥进行解密。 你可以将…

【Kettle的安装与使用】使用Kettle实现mysql和hive的数据传输(使用Kettle将mysql数据导入hive、将hive数据导入mysql)

文章目录 一、安装1、解压2、修改字符集3、启动 二、实战1、将hive数据导入mysql2、将mysql数据导入到hive 一、安装 Kettle的安装包在文章结尾 1、解压 在windows中解压到一个非中文路径下 2、修改字符集 修改 spoon.bat 文件 "-Dfile.encodingUTF-8"3、启动…

【机器学习】 15. SVM 支撑向量机 support vector machine,拉格朗日,软边界,核函数

SVM 支撑向量机 support vector machine&#xff0c;拉格朗日&#xff0c;软边界&#xff0c;核函数 1. 超平面边界 margin of hyperplane2. 边界越大的超平面越好原因 3. 线性模型通过决策边界分类4. SVM的问题5. 拉格朗日乘子与SVM结合求最大边界6. SVM软边界和硬边界7. 非线…

多线程学习篇六:park / unpark

1. API LockSupport.park()&#xff1a;暂停当前线程LockSupport.unpark (线程对象)&#xff1a;恢复某个线程的运行 1.1 先 park 再 unpark main 线程睡眠时间大于 t1 线程睡眠时间 Slf4j(topic "c.Test01") public class Test01 {public static void main(Str…

传承双百基因 大将军F9轻松跑“盈”脐橙创富路

“江作青罗带&#xff0c;山如碧玉簪。”广西河池&#xff0c;地处桂林西北一隅&#xff0c;奇秀的喀斯特地貌纵横绵延&#xff0c;亚热带季风气候温润宜人&#xff0c;堪称种植脐橙的“天选之地”。 正值秋季&#xff0c;这里漫山遍野&#xff0c;“橙”香四溢&#xff0c;大量…

一图看懂亚信安全2024年三季度财报

一图看懂亚信安全2024年三季度财报&#xff0c; 2024年前三季度营收创历史新高&#xff0c; 净利润、经营现金流加速增长&#xff01; &#xff08;相关信息主要摘自亚信安全2024年三季度财报&#xff0c; 如存在差异&#xff0c;以亚信安全2024年三季度财报为准。&#xff0…

arm 体系架构-过程调用标准AAPCS

一、什么是AAPCS&#xff1f; 旧时&#xff0c;ARM 过程调用标准叫做 APCS (ARM Procedure Call Standard)&#xff0c;Thumb的过程调用标准为 TPCS。如今这两种叫法已经废弃&#xff0c;统一称作 AAPCS (Procedure Call Standard for the ARM Architecture)。 AAPCS 是 ARM …

Kubernetes运行大数据组件-运行spark

部署组件 ● spark-historyserver ● spark-client 配置文件 kind: ConfigMap apiVersion: v1 metadata:name: spark data:spark-defaults.conf: |-spark.eventLog.enabled truespark.eventLog.dir hdfs://192.168.199.56:8020/eventLogsspark.ev…

STM32FreeRTOS 使用QSPI驱动nandFlash

STM32FreeRTOS 使用QSPI驱动nandFlash 不清楚为什么STM32同时打开3个以上的音频文件时会出现播放问题&#xff0c;所以更换方案。因为SRAM的内存空间过小&#xff0c;用于存储音频文件不适合&#xff0c;所以使用大小为128MByte的nandFlash。 nandFlash使用华邦的W25N01GVZEI…

Nature Communications|综述|无线胶囊内窥镜机器人的最新研究进展和未来发展方向(健康监测/柔性传感/可吞服电子)

浙江大学杨华勇(Huayong Yang)院士和韩冬( Dong Han)特聘研究员团队,在期刊《Nature Communications》上发布了一篇题为“Robotic wireless capsule endoscopy: recent advances and upcoming technologies”的综述论文,博士生曹青(Qing Cao)为论文第一作者。综述内容如…

群控系统服务端开发模式-应用开发-安装及提交仓库

整个应用采用的是现有的流行模式&#xff0c;前后分离。应用架构前端采用vue-element-admin&#xff0c;API接口采用的是thinkphp6&#xff0c;数据库采用的是MySQL5.7.36&#xff0c;而事件处理我采用的是分布式队列rabbitMQ。 首先安装及调整API接口系统业务架构逻辑。根据《…

一文讲明白大模型分布式逻辑(从GPU通信原语到Megatron、Deepspeed)

1. 背景介绍 如果你拿到了两台8卡A100的机器&#xff08;做梦&#xff09;&#xff0c;你的导师让你学习部署并且训练不同尺寸的大模型&#xff0c;并且写一个说明文档。你意识到&#xff0c;你最需要学习的就是关于分布式训练的知识&#xff0c;因为你可是第一次接触这么多卡…

Unreal Engine 5 C++(C#)开发:使用蓝图库实现插件(一)认识和了解Build.cs

目录 引言 一、创建一个C插件TextureReader插件 二、Build.cs文件 三、ModuleRules 四、TextureReader插件的构造 4.1ReadOnlyTargetRules的作用 4.2TextureReaderd的构造调用 4.3设置当前类的预编译头文件的使用模式 4.4PublicIncludePaths.AddRange与PrivateInclude…

揭秘世界技能大赛健康与社会照护项目,对智慧养老专业建设的启示

一、世界技能大赛&#xff08;世赛&#xff09;&#xff1a;职业技能的巅峰对决 被誉为“职业技能奥林匹克”的世界技能大赛是全球最高水平的职业技能竞赛&#xff0c;代表着各行业职业技能发展的国际先进水平。赛事涵盖六大领域&#xff1a;建筑与工程技术、创意艺术与时尚、…