2020百度C++笔试题解(3.29)

基础的选择题说实话不太行,基础不太扎实,然后编程题倒是不太难,这边写一下题解。

第一题

题意

大概是给你一个n,然后找一对a,b满足a,b都小于n。并且lcm(a,b)-gcd(a,b)最小。

分析

一开始以为和一道做过的cf题一样,仔细想了下发现更简单,这个就是要lcm最大同时gcd最小,gcd最小一定是1,同时使得lcm最大,那一定是n和n-1。于是答案就是n*(n-1)-1,注意要开longlong。

我的代码

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

ll n, ans;

int main() {
	while( cin >> n ) {
		ans = n * (n-1) - 1;
		cout << ans << endl;
	}
	return 0;
}

第二题

题意

两个人轮流取n组石头,每次取每组里面的其中1个,当取的人取的时候每一组都没有剩余石头即都是0,或者取完后有两组石头相同的时候就输。问最后谁赢。

分析

一开始以为是一个常规的博弈,后来发现题目看错了。这个题目也是思维题,可以模拟一下取石头,可以发现当石头取成形如(0, 1, 2, 3, 4…)时,下一个人必输。于是我们可以计算需要几步可以取成如下情形,那么此时下一个人必输。不过不要忘记一些特殊情况,一开始就有3组以上相同(如2, 2, 2),一开始就有两个以上相同的两组(如4, 4, 5, 5),还有全是0的。

我的代码

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

int T, n;
int a[100005];
int sum;

int main() {
	scanf("%d",&T);
	while(T--) {
		map<int, int> M;
		int flag2 = 0, flag3 = 0;
		scanf("%d",&n); sum = 0;
		for (int i=1; i<=n; ++i) {
			scanf("%d",&a[i]);
			sum+=a[i];
			M[a[i]]++;
			if ( M[a[i]] == 2 ) flag2++;
			if ( M[a[i]] == 3 ) flag3++;
		}
        if ( flag3 ) printf("woman\n");
        else if ( flag2 >= 2 ) printf("woman\n");
		else if ( (sum-n*(n-1)/2) % 2 == 0 ) printf("woman\n");
		else printf("man\n");
	}
	return 0;
}

第三题

题意

有一个飞船从n*m大小的矩形的左侧飞到右侧,然后中间有很多点,求离所有点包括上下边界的距离的最小值的最大值。其实就是求你这条路径到离得最近的点(或者上下边界)的距离,使得这个距离最大。

分析

初步考虑二分距离,然后判断该距离是否可行。判断的话就是把每个点看作一个圆,圆的内部是不能走的,看一下这些圆会不会堵住上下边界。因为给的点的个数为k个,k最大6000,这个复杂度的话直接暴力判断是不行的。于是我的想法是用并查集合并有交集的点,如果这些有交集的点能覆盖整个上下边界,那么就说明是不存在路的。这样复杂度就变成了60006000二分次数。其实这样的时间复杂度有点玄的,一开始也确实只过了一半,然后不断调整参数,优化,最后终于调到了100%。

我的代码

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

#define MAXN 6005

double up, down;
int n, m, k;
double x[MAXN], y[MAXN];
int fa[MAXN];
int u[MAXN], d[MAXN];
double dist[MAXN][MAXN];

inline
void init() {
	for ( int i=0; i<=k; ++i )
		fa[i]=i;
}

inline
int find(int x) {
	if ( fa[x] == x ) return x;
	return fa[x] = find( fa[x] );
}

inline
void combine( int x, int y ) {
	int fx = find(x), fy = find(y);
	if ( fx == fy ) return;
	fa[fy] = fx;
}

inline
double dis( int i, int j ) {
	return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}

bool judge( double x ) {
	init();
	for ( int i = 1; i <= k; ++i ) {
        u[i] = d[i] = 0;
		for ( int j = i+1; j <= k; ++j ) {
			if ( dist[i][j] <= 2 * x )
				combine(i, j);
		}
	}
	for ( int i = 1; i <= k; ++i ) {
		int f = find(i);
		if ( y[i] + x > up ) u[f] = 1;
		if ( y[i] - x < down ) d[f] = 1;
		if ( u[f] && d[f] ) return false;
	}
	return true;
}

int main() {
	scanf("%d%d%d",&n, &m, &k);
	for ( int i=1; i<=k; ++i ) {
		scanf("%lf%lf", &x[i], &y[i]);
	}
	for ( int i = 1; i <= k; ++i ) {
        u[i] = d[i] = 0;
		for ( int j = i+1; j <= k; ++j ) {
			dist[i][j] = dis(i,j);
		}
	}
	double l=0, r=5e5, mid;
	for ( int i=1; i<=45; ++i )
	{
		mid = (l+r) / 2.0;
		up = m - mid;
		down = mid;
		if ( judge(mid) ) {
			l = mid;
		} else {
			r = mid;
		}
	}
	printf("%.4lf\n",mid);
	return 0;
}
发布了136 篇原创文章 · 获赞 33 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Radium_1209/article/details/105203076