2019南京站(重温经典)

2023-11-22 21:59
文章标签 经典 2019 重温 南京站

本文主要是介绍2019南京站(重温经典),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2019南京站(重温经典)

  • 导语
  • 涉及的知识点
  • 题目
    • A
    • C
    • H
    • J
    • K
  • 参考文献

导语

日常练习,这一次做的不是很满意

涉及的知识点

思维,乘法逆元,组合数学,拓扑排序,DP,二分图最大权匹配,平面几何

链接:南京2019区域赛 [Cloned]

题目

A

题目大意:给出一个正整数n,找到一个最小的整数k使得集合 { 1 , 2 , … n } \{1,2,\dots n\} {1,2,n}的任意一个大小为 k k k的子集都至少存在两个元素使得其中一个是另一个的因子

思路:一开始认为是素数个数加1,但后来找到了反例: 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 1,2,3,4,5,6,7,8,9 1,2,3,4,5,6,7,8,9,如果按照素数个数加一,那么k的大小为5,但是可以找到 { 5 , 6 , 7 , 8 , 9 } \{5,6,7,8,9\} {5,6,7,8,9}这个集合不满足条件
最简单的方法是直接找规律,可以发现k的大小为 2 , 3 , 3 , 4 , 4 … 2,3,3,4,4\dots 2,3,3,4,4,结果就是 ( n + 1 ) / 2 + 1 (n+1)/2+1 (n+1)/2+1

代码

#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int T,n;
int main() {cin.tie(0);ios::sync_with_stdio(0);cin >>T;while(T--) {cin >>n;cout <<(n+1)/2+1<<endl;}return 0;
}

C

题目大意:给出一个数字矩阵,对路径的定义:从起始格到终点上元素必须严格递增,公差为1,并且终点之后不可再拓展,格子数不得小于4,求出路径条数

思路:一开始从方案数的方向取考虑,是没错的,但是对于4以及多于4的路径的统计就出现了问题,最后看了题解才知道,忽略了一个比较重要的点:终点之后不可拓展,但是可以从终点向前取4个,5个等,也就是,长度为7的路径,可以创造出长度为4,5,6,7的路径,那么其实可以将4以及4之后的方案数视为一个整体
d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示以 ( i , j ) (i,j) (i,j)为终点,长度为k的路径条数,可以得到这样的递推式: d p [ i ] [ j ] [ k ] = d p [ i ] [ j ] [ k ] + d p [ i ′ ] [ j ′ ] [ k − 1 ] dp[i][j][k]=dp[i][j][k]+dp[i'][j'][k-1] dp[i][j][k]=dp[i][j][k]+dp[i][j][k1] ( i ′ , j ′ ) (i',j') (i,j) ( i , j ) (i,j) (i,j)的相邻格,元素之差为1且 ( i , j ) (i,j) (i,j)数据更大
在基本上确定了dp的取法与定义后,接下来就是决定dp的顺序,对于任何路径来说,第一个点必然没有其他相邻点比它小,那么可以用DAG中出度与入度的概念,有比该点大1的相邻格,该点出度+1,有比该点小1的相邻格,该点入度-1,之后可以通过拓扑排序,构造不同路径长度下的可行方案数,其余见代码

代码

#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int n,m,in[1212][1212],out[1212][1212],maze[1212][1212],Next[4][2]= {0,1,1,0,0,-1,-1,0};
ll res,dp[1212][1212][5];
const int mod=1e9+7;
struct node {int x,y;
};
void BFS() {queue<node>q;for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)if(!in[i][j]) {//录入入度为0的节点,准备拓扑BFSq.push({i,j});dp[i][j][1]=1;}while(!q.empty()) {auto t=q.front();q.pop();int x=t.x,y=t.y;for(int i=0; i<4; i++) {int xx=x+Next[i][0],yy=y+Next[i][1];if(xx<1||yy<1||xx>n||yy>m)continue;if(maze[xx][yy]==maze[x][y]+1) {//邻接点可拓展,更新对应的方案数dp[xx][yy][2]=(dp[x][y][1]+dp[xx][yy][2])%mod;//邻接点长度为2方案数来自于(x,y)长度为1的方案dp[xx][yy][3]=(dp[x][y][2]+dp[xx][yy][3])%mod;//邻接点长度为3方案数来自于(x,y)长度为2的方案dp[xx][yy][4]=(dp[x][y][3]+dp[xx][yy][4]+dp[x][y][4])%mod;//邻接点长度大于等于4方案数来自于(x,y)长度为3的方案数与大于等于4的方案数if(--in[xx][yy]==0)q.push({xx,yy});//拓扑排序,出现新的根节点}}}
}
int main() {cin.tie(0);ios::sync_with_stdio(0);cin >>n>>m;for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)cin >>maze[i][j];for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)for(int k=0; k<4; k++) {int x=i+Next[k][0],y=j+Next[k][1];if(x<1||y<1||x>n||y>m)continue;if(maze[i][j]==maze[x][y]+1)in[i][j]++;//统计入度出度if(maze[i][j]==maze[x][y]-1)out[i][j]++;//同上}BFS();//广搜统计方案数for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)if(!out[i][j])res=(res+dp[i][j][4])%mod;//对于出度为0的点统计经过该点长度大于等于4的方案数cout <<res;return 0;
}

H

题目大意:a需要找b,有三类人,支持a找到b(包括a),不支持,无所谓,每个人(除了a)都在不同的房间里,对每一个人可以询问三种问题:b在几号房,你是谁,谁在x号房,支持者会给出真,不支持者会给出假,第三类会随意给出,现在给出三类人的数量,现在判断a是否能找到b,如果能找到,至少询问几个问题

思路:如果支持者大于另两类之和,显然a总能找到b,因为a只要问下一个人,他必定答真,如果给出的数量为1,0,0,代表只有一个b,就无需询问了

代码

#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int a,b,c;
int main() {cin.tie(0);ios::sync_with_stdio(0);cin >>a>>b>>c;if(a==1&&b==0&&c==0)cout <<"YES\n0";else if(a>b+c)cout <<"YES\n"<<2*(b+c)+1;else cout <<"NO";return 0;
}

J

题目大意:略

思路:KM模板题,需要注意图的构造,构造完后需要使用 O ( n 3 ) O(n^3) O(n3)的模板求最大权完美匹配

代码

#include <bits/stdc++.h>
#define int long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=512;
int pre[maxn],match[maxn],delta[maxn],graph[maxn][maxn],n,res,l[maxn],r[maxn];
int a[maxn],p[maxn],b[maxn],c[maxn];
bool visl[maxn],visr[maxn];
void maxmatch(int u) {int x,y=0,d,id=0;memset(pre,0,sizeof(pre));//pre用来记录上一条边for(int i=1; i<=n; i++)delta[i]=inf;//初始化右点集match[y]=u;//初始化匹配关系while(1) {x=match[y];d=inf;//初始化visr[y]=1;//访问for(int i=1; i<=n; i++) {if(visr[i])continue;if(delta[i]>l[x]+r[i]-graph[x][i]) {//能否加一条边x-idelta[i]=l[x]+r[i]-graph[x][i];pre[i]=y;//连接一条未匹配边}if(delta[i]<d) {//找到一条修改值最少的点d=delta[i];//记录数值id=i;//记录编号}}for(int i=0; i<=n; i++)if(visr[i])l[match[i]]-=d,r[i]+=d;//尝试修改else delta[i]-=d;//该边不是最短边,减去后可能成为最短边y=id;if(match[y]==-1)break;//无法继续匹配}while(y) {//构造匹配match[y]=match[pre[y]];y=pre[y];}
}
int KM() {memset(match,-1,sizeof(match));//清空匹配memset(l,0,sizeof(l));memset(r,0,sizeof(r));for(int i=1; i<=n; i++) {memset(visr,0,sizeof(visr));maxmatch(i);//BFS左点集}for(int i=1; i<=n; i++)if(match[i]!=-1)res+=graph[match[i]][i];return res;
}
signed main() {ios::sync_with_stdio(0);cin.tie(0);cin >>n;for(int i=1; i<=n; i++)cin >>a[i];for(int i=1; i<=n; i++)cin >>p[i];for(int i=1; i<=n; i++)cin >>b[i];for(int i=1; i<=n; i++)cin >>c[i];//录入数据for(int i=1; i<=n; i++)for(int j=1; j<=n; j++)for(int k=1; k<=n; k++)if(b[i]+c[j]>a[k])graph[i][j]+=p[k];//如果可以打败,建边cout <<KM();return 0;
}
/*
4
1 2 3 4
1 1 1 1
0 0 1 1
0 1 1 2
*/

K

题目大意:给出一个三角形,给出一个点,如果这个点不在边界上输出-1,如果点在边界上,求出另一个点,使得两点间连线能够将三角形平分成两个面积相等的部分

思路:首先判断给出的点是否在边界上,如果不在就直接输出-1,如果在,就尝试另外两条边上的两点,求出总三角形面积,如图,求出三角形在不同情况下满足总面积/2的高,然后根据高算出对应坐标即可
在这里插入图片描述

代码

#include <bits/stdc++.h>
using namespace std;typedef long long ll;const double eps = 1e-10;int sign(double x)//判断浮点数的符号
{if(fabs(x) <= eps) return 0;if(x > 0) return 1;else return -1;
}struct Point
{double x,y;Point() {}//定义运算Point(double _x,double _y){x = _x;y = _y;}Point operator + (const Point &b)const{return Point(x+b.x,y+b.y);}Point operator - (const Point &b)const{return Point(x-b.x,y-b.y);}Point operator * (const double &k)const //乘常数{return Point(x*k,y*k);}Point operator / (const double &k)const{return Point(x/k,y/k);}double len(){return x * x + y * y;}
};
typedef Point Vector;//定义将点重定义为向量
Point p[4],pp;//直接预定义变量,p三个点,pp一个点double cross(Vector a,Vector b)//叉积
{return a.x * b.y - a.y * b.x;
}
double dot(Vector a,Vector b)//点积
{return a.x * b.x + a.y * b.y;
}
double dis(Point a,Point b)//两点之间的距离
{return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
Point answer(int flag)
{Point ans;if(flag == 1){double d1 = dis(pp,p[2]);double d2 = dis(pp,p[3]);if(fabs(d1 - d2) <= eps)ans = p[1];else{double rate;Vector v1,v2,v3;if(d1 > d2){v1 = pp - p[2],v2 = p[1] - p[2],v3 = p[3] - p[2];double dd = fabs(cross(v1,v2)) / v2.len();double hh = fabs(cross(v3,v2)) / v2.len();rate = hh / dd;ans = p[2] + (p[1]-p[2]) * 0.5 * rate;}else{v1 = pp - p[3],v2 = p[1] - p[3],v3 = p[2] - p[3];double dd = fabs(cross(v1,v2)) / v2.len();double hh = fabs(cross(v3,v2)) / v2.len();rate = hh / dd;ans = p[3] + (p[1]-p[3]) * 0.5 * rate;}}}else if(flag == 2){double d1 = dis(pp,p[1]);double d2 = dis(pp,p[3]);if(fabs(d1 - d2) <= eps)ans = p[2];else{double rate;Vector v1,v2,v3;if(d1 > d2){v1 = pp - p[1],v2 = p[2] - p[1],v3 = p[3] - p[1];double dd = fabs(cross(v1,v2)) / v2.len();double hh = fabs(cross(v3,v2)) / v2.len();rate = hh / dd;ans = p[1] + (p[2]-p[1]) * 0.5 * rate;}else{v1 = pp - p[3],v2 = p[2] - p[3],v3 = p[1] - p[3];double dd = fabs(cross(v1,v2)) / v2.len();double hh = fabs(cross(v3,v2)) / v2.len();rate = hh / dd;ans = p[3] + (p[2]-p[3]) * 0.5 * rate;}}}else if(flag == 3){double d1 = dis(pp,p[1]);double d2 = dis(pp,p[2]);if(fabs(d1 - d2) <= eps)ans = p[3];else{double rate;Vector v1,v2,v3;if(d1 > d2){v1 = pp - p[1],v2 = p[3] - p[1],v3 = p[2] - p[1];double dd = fabs(cross(v1,v2)) / v2.len();double hh = fabs(cross(v3,v2)) / v2.len();rate = hh / dd;ans = p[1] + (p[3]-p[1]) * 0.5 * rate;}else{v1 = pp - p[2],v2 = p[3] - p[2],v3 = p[1] - p[2];double dd = fabs(cross(v1,v2)) / v2.len();double hh = fabs(cross(v3,v2)) / v2.len();rate = hh / dd;ans = p[2] + (p[3]-p[2]) * 0.5 * rate;}}}return ans;
}
void solve()
{Point ans;for(int i = 1; i <= 3; i ++)scanf("%lf%lf",&p[i].x,&p[i].y);scanf("%lf%lf",&pp.x,&pp.y);if(pp.x == p[1].x && pp.y == p[1].y)//判断第四个点是否是端点{Point mid = (p[2] + p[3]) / 2.0;printf("%.10f %.10f\n",mid.x,mid.y);return ;}if(pp.x == p[2].x && pp.y == p[2].y){Point mid = (p[1] + p[3]) / 2.0;printf("%.10f %.10f\n",mid.x,mid.y);return ;}if(pp.x == p[3].x && pp.y == p[3].y){Point mid = (p[1] + p[2]) / 2.0;printf("%.10f %.10f\n",mid.x,mid.y);return ;}int flag = 0;//判断第四个点是否合法Vector v1 = pp - p[1],v2 = pp - p[2],v3 = pp - p[3];if(sign(dot(v1,v2)) == -1 && sign(cross(v1,v2)) == 0) flag = 3;else if(sign(dot(v1,v3)) == -1 && sign(cross(v1,v3)) == 0) flag = 2;else if(sign(dot(v2,v3)) == -1 && sign(cross(v2,v3)) == 0) flag = 1;if(!flag){printf("-1\n");return ;}ans=answer(flag);//flag 1表示在p2和p3两点之间的边上,2表示在p1和p3之间的边上,3表示在p1和p2之间的边上printf("%.10f %.10f\n", ans.x, ans.y);
}int main()
{int T;scanf("%d",&T);while(T--){solve();}return 0;
}

参考文献

  1. Digital Path(记忆化搜索)

这篇关于2019南京站(重温经典)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/413189

相关文章

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

HotSpot虚拟机的经典垃圾收集器

读《深入理解Java虚拟机》第三版笔记。 关系 Serial、ParNew、Parallel Scavenge、Parallel Old、Serial Old(MSC)、Concurrent Mark Sweep (CMS)、Garbage First(G1)收集器。 如图: 1、Serial 和 Serial Old 收集器 2、ParNew 收集器 3、Parallel Sc

STL经典案例(四)——实验室预约综合管理系统(项目涉及知识点很全面,内容有点多,耐心看完会有收获的!)

项目干货满满,内容有点过多,看起来可能会有点卡。系统提示读完超过俩小时,建议分多篇发布,我觉得分篇就不完整了,失去了这个项目的灵魂 一、需求分析 高校实验室预约管理系统包括三种不同身份:管理员、实验室教师、学生 管理员:给学生和实验室教师创建账号并分发 实验室教师:审核学生的预约申请 学生:申请使用实验室 高校实验室包括:超景深实验室(可容纳10人)、大数据实验室(可容纳20人)、物联网实验

从计组中从重温C中浮点数表示及C程序翻译过程

目录 移码​编辑  传统浮点表示格式 浮点数的存储(ieee 754)->修炼内功 例子:   ​编辑 浮点数取的过程   C程序翻译过程 移码  传统浮点表示格式 浮点数的存储(ieee 754)->修炼内功 根据国际标准IEEE(电⽓和电⼦⼯程协会)  32位 例子:    64位    IEEE754对有效数字M和

嵌入式面试经典30问:二

1. 嵌入式系统中,如何选择合适的微控制器或微处理器? 在嵌入式系统中选择合适的微控制器(MCU)或微处理器(MPU)时,需要考虑多个因素以确保所选组件能够满足项目的具体需求。以下是一些关键步骤和考虑因素: 1.1 确定项目需求 性能要求:根据项目的复杂度、处理速度和数据吞吐量等要求,确定所需的处理器性能。功耗:评估系统的功耗需求,选择低功耗的MCU或MPU以延长电池寿命或减少能源消耗。成本

Leetcode面试经典150题-128.最长连续序列-递归版本另解

之前写过一篇这个题的,但是可能代码比较复杂,这回来个简洁版的,这个是递归版本 可以看看之前的版本,两个版本面试用哪个都保过 解法都在代码里,不懂就留言或者私信 class Solution {/**对于之前的解法,我现在提供一共更优的解,但是这种可能会比较难懂一些(思想方面)代码其实是很简洁的,总体思想如下:不需要排序直接把所有数放入map,map的key是当前数字,value是当前数开始的

力扣 739. 每日温度【经典单调栈题目】

1. 题目 理解题意: 1.1. 给一个温度集合, 要返回一个对应长度的结果集合, 这个结果集合里面的元素 i 是 当前 i 位置的元素的下一个更高温度的元素的位置和当前 i 位置的距离之差, 若是当前元素不存在下一个更高温度的元素, 则这个位置用0代替; 2. 思路 本题用单调栈来求解;单调栈就适用于来求当前元素左边或者右边第一个比当前元素大或者小的元素;【单调栈:让栈中的元素保持单调

接口自动化三大经典难题

目录 一、接口项目不生成token怎么解决关联问题 1. Session机制 2. 基于IP或设备ID的绑定 3. 使用OAuth或第三方认证 4. 利用隐式传递的参数 5. 基于时间戳的签名验证 二、接口测试中网络问题导致无法通过怎么办 1. 重试机制 2. 设置超时时间 3. 使用模拟数据 4. 网络问题的预检测 5. 日志记录与错误分析 6. 切换网络环境 7.

嵌入式面试经典30问:一

什么是嵌入式系统? 嵌入式系统是指嵌入到某个对象体系中的专用计算机系统,它负责执行特定的任务,具有专用性、隐蔽性、资源受限和可靠性要求高等特点。通常包括硬件和软件两部分,硬件以微处理器为核心,软件则负责控制和管理硬件资源,实现特定的应用功能。 嵌入式系统和普通计算机系统有什么区别? 嵌入式系统与普通计算机系统的主要区别在于目的、资源、性能和成本等方面。嵌入式系统通常针对特定应用设计,具有体积小

UVA10071(重温高中物理公式)

Back to High School Physics Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu 题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18809 Description A parti