热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

第六周周赛题解

A题这题贼水,直接暴力就可以了。用个bool数组记录一下,如果某一天,当前剩下的最大的出现了的话,就输出一段。1#include<stdio.h>2intn;3boolvi

A题

这题贼水,直接暴力就可以了。

用个bool数组记录一下,如果某一天,当前剩下的最大的出现了的话,就输出一段。

 1 #include
2 int n;
3 bool vis[100010];
4 int main()
5 {
6 scanf("%d",&n);
7 int x;
8 int now=n;
9 for(int i=1;i<=n;++i)
10 {
11 scanf("%d",&x);
12 vis[x]=1;
13 if(vis[now])
14 {
15 printf("%d",now);
16 --now;
17 while(vis[now])
18 {
19 printf(" %d",now);
20 --now;
21 }
22 }
23 printf("\n");
24 }
25 return 0;
26 }
View Code

B题

又是水题,你们肯定要感谢我

只要求每个数对最大的数的绝对值的和就可以了

 1 #include
2 #include
3 using namespace std;
4 int n, ai;
5 int main()
6 {
7 scanf("%d", &n);
8 int maxi = 0;
9 int sum = 0;
10 for (int i = 0; i )
11 {
12 scanf("%d", &ai);
13 sum += ai;
14 maxi = max(maxi, ai);
15 }
16 int res = maxi * n - sum;
17 printf("%d", res);
18 return 0;
19 }
View Code

C题

这一题开始就有点难了,DFS+回溯

题目大意: 任选一个起点,按照国际象棋马的跳法,不重复的跳完整个棋盘,如果有多种路线则选择字典序最小的路线(路线是点的横纵坐标的集合,注意棋盘的横坐标的用大写字母,纵坐标是数字)

 

1. 应该看到这个题就可以想到用DFS,当首先要明白这个题的意思是能否只走一遍(不回头不重复)将整个地图走完,而普通的深度优先搜索是一直走,走不通之后沿路返回到某处继续深搜。所以这个题要用到的回溯思想,如果不重复走一遍就走完了,做一个标记,算法停止;否则在某种DFS下走到某一步时按马跳的规则无路可走而棋盘还有为走到的点,这样我们就需要撤消这一步,进而尝试其他的路线(当然其他的路线也可能导致撤销),而所谓撤销这一步就是在递归深搜返回时重置该点,以便在当前路线走一遍行不通换另一种路线时,该点的状态是未访问过的,而不是像普通的DFS当作已经访问了。

 

2. 如果有多种方式可以不重复走一遍的走完,需要输出按字典序最小的路径,而注意到国际象棋的棋盘是列为字母,行为数字,如果能够不回头走一遍的走完,一定会经过A1点,所以我们应该从A1开始搜索,以确保之后得到的路径字典序是最小的(也就是说如果路径不以A1开始,该路径一定不是字典序最小路径),而且我们应该确保优先选择的方向是字典序最小的方向,这样我们最先得到的路径就是字典序最小的。

 

 1 #include 
2 #include
3 #include<string.h>
4 using namespace std;
5
6 const int MAX_N = 27;
7
8 const int dx[8] = {-1, 1, -2, 2, -2, 2, -1, 1};
9 const int dy[8] = {-2, -2, -1, -1, 1, 1, 2, 2};
10 bool visited[MAX_N][MAX_N];
11 struct Step{
12 char x, y;
13 } path[MAX_N];
14 bool success; //是否成功遍历的标记
15 int cases, p, q;
16
17 void DFS(int x, int y, int num);
18
19 int main()
20 {
21 scanf("%d", &cases);
22 for (int c = 1; c <= cases; c++)
23 {
24 success = false;
25 scanf("%d%d", &p, &q);
26 memset(visited, false, sizeof(visited));
27 visited[1][1] = true; //起点
28 DFS(1, 1, 1);
29 printf("Scenario #%d:\n", c);
30 if (success)
31 {
32 for (int i = 1; i <= p * q; i++)
33 printf("%c%c", path[i].y, path[i].x);
34 printf("\n");
35 }
36 else
37 printf("impossible\n");
38 if (c != cases)
39 printf("\n"); //注意该题的换行
40 }
41 return 0;
42 }
43
44 void DFS(int x, int y, int num)
45 {
46 path[num].y = y + 'A' - 1; //int 转为 char
47 path[num].x = x + '0';
48 if (num == p * q)
49 {
50 success = true;
51 return;
52 }
53 for (int i = 0; i <8; i++)
54 {
55 int nx = x + dx[i];
56 int ny = y + dy[i];
57 if (0 0 q
58 && !visited[nx][ny] && !success)
59 {
60 visited[nx][ny] = true;
61 DFS(nx, ny, num+1);
62 visited[nx][ny] = false; //撤销该步
63 }
64 }
65 }
View Code

 

D题

这题是我原创的题目233,其实是一道有关分治的裸题,其实就是最接近点对问题

给定平面S上n个点,找其中的一对点,使得在n(n-1)/2 个点对中,该点对的距离最小。

算法思路就是

 1) n较小时直接求 (n=2).                                                         
2) 将S上的n个点分成大致相等的2个子集S1和S2
3) 分别求S1和S2中的最接近点对
4) 求一点在S1、另一点在S2中的最近点对
5) 从上述三对点中找距离最近的一对.

仔细分析上面的过程,只有第4步有些困难,其它几个步骤只要递归下去就行了。看下面这个图,我们把点分成了左右两部分S1和S2,并且分别求得了最小距离为dl,dr。 令 d = min(dl,dr):

divide_points_new1

接下来要考虑的就是 两个端点分别在左右两部分中的点对。已经知道最小距离不会超过d。我们在拆分两部分的时候把 P [N/2] 作为中间点。做一条过P的垂直线,并找到所有距离垂直线距离在d以内的点,把这些点放在数组strip[] 中,如下图所示。其它点就可以不用考虑了。

strip_closesr1

接下来计算strip[]中的最小距离点对。按照y坐标排序,这一步需要O(nLogn)的复杂度,其实可以 通过递归和归并优化到O(n)。由于已经排序,我们可以再O(n)内找到最小距离点对d3(这里其实需要一些几何知识来证明,参考:http://people.csail.mit.edu/indyk/6.838-old/handouts/lec17.pdf)。

贴上学长T^T的代码

 1 #include 
2 #include
3 #include
4 #include
5 #include
6 using namespace std;
7 const double INF = 1e20;
8 const int N = 100005;
9
10 struct Point
11 {
12 double x;
13 double y;
14 }point[N];
15 int n;
16 int tmpt[N];
17
18 bool cmpxy(const Point& a, const Point& b)
19 {
20 if(a.x != b.x)
21 return a.x < b.x;
22 return a.y < b.y;
23 }
24
25 bool cmpy(const int& a, const int& b)
26 {
27 return point[a].y < point[b].y;
28 }
29
30 double min(double a, double b)
31 {
32 return a a : b;
33 }
34
35 double dis(int i, int j)
36 {
37 return sqrt((point[i].x-point[j].x)*(point[i].x-point[j].x)
38 + (point[i].y-point[j].y)*(point[i].y-point[j].y));
39 }
40
41 double Closest_Pair(int left, int right)
42 {
43 double d = INF;
44 if(left==right)
45 return d;
46 if(left + 1 == right)
47 return dis(left, right);
48 int mid = (left+right)>>1;
49 double d1 = Closest_Pair(left,mid);
50 double d2 = Closest_Pair(mid+1,right);
51 d = min(d1,d2);
52 int i,j,k=0;
53 //分离出宽度为d的区间
54 for(i = left; i <= right; i++)
55 {
56 if(fabs(point[mid].x-point[i].x) <= d)
57 tmpt[k++] = i;
58 }
59 sort(tmpt,tmpt+k,cmpy);
60 //线性扫描
61 for(i = 0; i )
62 {
63 for(j = i+1; j )
64 {
65 double d3 = dis(tmpt[i],tmpt[j]);
66 if(d > d3)
67 d = d3;
68 }
69 }
70 return d;
71 }
72
73
74 int main()
75 {
76 while(~scanf("%d",&n))
77 { for(int i = 0; i )
78 scanf("%lf %lf",&point[i].x,&point[i].y);
79 sort(point,point+n,cmpxy);
80 printf("%lf\n",Closest_Pair(0,n-1));
81 }
82 return 0;
83 }
View Code

 

E题

这题几何题233。

解法如下:不需要正规的三角剖分,用求多边形面积的思想,从一点出发连接多边形的边得到很多三
角形,三角形有向边方向决定有向面积有正有负,相加得到多边形面积的正值或负值。
把两个多边形都分成若干这样的三角形,求每对三角形的交,根据两三角形有向边顺逆时
针关系确定相交面积的正负号,最后两多边形面积和减去相交面积。

  1 #include
2 #include<string.h>
3 #include
4 #include
5 #include
6 const int maxn = 555;
7 const int maxisn = 10;
8 const double eps = 1e-8;
9 const double pi = acos(-1.0);
10 int dcmp(double x)
11 {
12 if(x > eps) return 1;
13 return x <-eps ? -1 : 0;
14 }
15 inline double min(double a, double b)
16 {return a a : b;}
17 inline double max(double a, double b)
18 {return a > b ? a : b;}
19 inline double Sqr(double x)
20 {return x * x;}
21 struct Point
22 {
23 double x, y;
24 Point(){x = y = 0;}
25 Point(double a, double b)
26 {x = a, y = b;}
27 inline Point operator-(const Point &b)const
28 {return Point(x - b.x, y - b.y);}
29 inline Point operator+(const Point &b)const
30 {return Point(x + b.x, y + b.y);}
31 inline double dot(const Point &b)const
32 {return x * b.x + y * b.y;}
33 inline double cross(const Point &b, const Point &c)const
34 {return (b.x - x) * (c.y - y) - (c.x - x) * (b.y - y);}
35 };
36 Point LineCross(const Point &a, const Point &b, const Point &c, const Point &d)
37 {
38 double u = a.cross(b, c), v = b.cross(a, d);
39 return Point((c.x * v + d.x * u) / (u + v), (c.y * v + d.y * u) / (u + v));
40 }
41 double PolygonArea(Point p[], int n)
42 {
43 if(n <3) return 0.0;
44 double s = p[0].y * (p[n - 1].x - p[1].x);
45 p[n] = p[0];
46 for(int i = 1; i i)
47 s += p[i].y * (p[i - 1].x - p[i + 1].x);
48 return fabs(s * 0.5);
49 }
50 double CPIA(Point a[], Point b[], int na, int nb)//ConvexPolygonIntersectArea
51 {
52 Point p[maxisn], tmp[maxisn];
53 int i, j, tn, sflag, eflag;
54 a[na] = a[0], b[nb] = b[0];
55 memcpy(p, b, sizeof(Point) * (nb + 1));
56 for(i = 0; i 2; ++ i)
57 {
58 sflag = dcmp(a[i].cross(a[i + 1], p[0]));
59 for(j = tn = 0; j eflag)
60 {
61 if(sflag >= 0) tmp[tn ++] = p[j];
62 eflag = dcmp(a[i].cross(a[i + 1], p[j + 1]));
63 if((sflag ^ eflag) == -2)
64 tmp[tn ++] = LineCross(a[i], a[i + 1], p[j], p[j + 1]);
65 }
66 memcpy(p, tmp, sizeof(Point) * tn);
67 nb = tn, p[nb] = p[0];
68 }
69 if(nb <3) return 0.0;
70 return PolygonArea(p, nb);
71 }
72 double SPIA(Point a[], Point b[], int na, int nb)//SimplePolygonIntersectArea
73 {
74 int i, j;
75 Point t1[4], t2[4];
76 double res = 0, if_clock_t1, if_clock_t2;
77 a[na] = t1[0] = a[0], b[nb] = t2[0] = b[0];
78 for(i = 2; i i)
79 {
80 t1[1] = a[i - 1], t1[2] = a[i];
81 if_clock_t1 = dcmp(t1[0].cross(t1[1], t1[2]));
82 if(if_clock_t1 <0) std::swap(t1[1], t1[2]);
83 for(j = 2; j j)
84 {
85 t2[1] = b[j - 1], t2[2] = b[j];
86 if_clock_t2 = dcmp(t2[0].cross(t2[1], t2[2]));
87 if(if_clock_t2 <0) std::swap(t2[1], t2[2]);
88 res += CPIA(t1, t2, 3, 3) * if_clock_t1 * if_clock_t2;
89 }
90 }
91 return PolygonArea(a, na) + PolygonArea(b, nb) - res;
92 }
93 Point p1[maxn], p2[maxn];
94 int n1, n2;
95 int main()
96 {
97 int i;
98 while(scanf("%d%d", &n1, &n2) != EOF)
99 {
100 for(i = 0; i "%lf%lf", &p1[i].x, &p1[i].y);
101 for(i = 0; i "%lf%lf", &p2[i].x, &p2[i].y);
102 printf("%.2f\n", SPIA(p1, p2, n1, n2) + eps);
103 }
104 return 0;
105 }
View Code

F题

这题怎么说呢,题意就是:给一系列操作,每个操作有两个数t和k,t=0表示求k以内的最大反素数;t=1表示求小于k且与k互质的数的个数。

大概就是对第一个操作,直接用dfs求反素数就行了;

第二个操作素数筛法的思想预先打个表。

 1 #include
2 #include
3 const long long INF = (((long long)1)<<62)+1;
4 using namespace std;
5 const int MAXN = 300 + 10;
6 const double M=1e-8;
7 const int N=50100;
8 const int d[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
9 int n,m,st[N],lazy[N],a[N];
10 int p[16]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
11 long long ans,ip[N];
12 void init()
13 {
14 int i,j;
15 for(i=1;i//初始化i最多有i个与其互质的数
16 for(i=1;i)
17 {
18 for(j=i;j<=N;j+=i) ip[j]--; //i为j的因子,所以j与i不互质,第j个数的互质数减少1
19 if(!ip[ip[i]]) ip[ip[i]]=i; //此时ip[i]存的是不大于i的数与i互质的个数k=ip[i],
20 //如果ip[k]=0,表示小于i的所有数中,没有刚好有k个互质数的数
21 //故将ip[k]=i,表示刚好有k个与i互质的数个数最小为i
22 ip[i]=0; //标记刚好有k个互质数的数没有(不大于i的数不可能存在某个数与其互质的数的个数等于i);
23 }
24 }
25 void dfs(int k,long long num,long long sum,int limit)
26 {
27 if (sum>n) return ;
28 if (sum==n) ans=min(ans,num);
29 for (int i=1;i<=limit;i++) {
30 if (ans/p[k] 1)>n) break;
31 num*=p[k];
32 if (n%(sum*(i+1))==0)
33 dfs(k+1,num,sum*(i+1),i);
34 }
35 }
36 int main()
37 {
38 int i,j,cnt=1;
39 int t;
40 init();
41 scanf("%d",&t);
42 while(t--)
43 {
44 int t;
45 scanf("%d%d",&t,&n);
46 if (t) {
47 ans=ip[n];
48 }
49 else {
50 ans=INF;
51 dfs(0,1,1,62);
52 }
53 printf("Case %d: ",cnt++);
54 if (ans==0) puts("Illegal");
55 else if (ans>=INF) puts("INF");
56 else printf("%lld\n",ans);
57 }
58 }
View Code

 


推荐阅读
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 4554:[Tjoi2016&Heoi2016]游戏 ... [详细]
  • 查找给定字符串的所有不同回文子字符串原文:https://www ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 在2022年,随着信息化时代的发展,手机市场上出现了越来越多的机型选择。如何挑选一部适合自己的手机成为了许多人的困扰。本文提供了一些配置及性价比较高的手机推荐,并总结了选择手机时需要考虑的因素,如性能、屏幕素质、拍照水平、充电续航、颜值质感等。不同人的需求不同,因此在预算范围内找到适合自己的手机才是最重要的。通过本文的指南和技巧,希望能够帮助读者节省选购手机的时间。 ... [详细]
author-avatar
水源水足
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有