BJTU计算思维机试

目录

Problem A. 数位重排 (100)

有两种解决方案

(I)

(II)

Peoblem B.小青蛙找眼镜

 解决方法:使得跳跃到达的位置与目标位置的差为偶数即可

 Peoblem C.数七

Peoblem D. 宝石

 解决方法:枚举对称轴与对称半径即可

Peoblem E. 最短子序列

 解决方法:枚举左右边界即可

Peoblem F. 分糖果


 

 

Problem A. 数位重排 (100)

 

4beead3df5d1444ea0f5ad992657cbd8.png

 

有两种解决方案

(I)

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

int main()
{
	char s1[110];
	int arr[110], n;
	scanf("%s", s1);
	n = strlen(s1);
	for (int i = 0; i < n; i++)
		arr[i] = s1[i] - '0';
	next_permutation(arr, arr + n);
	for (int i = 0; i < n; i++)
		printf("%d", arr[i]);
	return 0;
}

(II)

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int main()
{
	char s1[110];
	int arr[110];
	scanf("%s", s1);
	int n;
	n = strlen(s1);
	for (int i = 0; i <= n; i++)
		arr[i] = s1[i] - '0';
	int bj = 0;
	for (int i = n - 2; i >= 0; i--)
	{
		if (arr[i] < arr[i + 1])
		{
			bj = i;
			break;
		}
	}
	for (int i = n - 1; i > bj; i--)
	{
		if (arr[bj] < arr[i])
		{
			swap(arr[bj], arr[i]);
			break;
		}
	}
	sort(arr + bj + 1, arr + n);
	for (int i = 0; i < n; i++)
		printf("%d", arr[i]);
	return 0;
}

Peoblem B.小青蛙找眼镜

82ecfdf21cdf487180cb45ad3ca40eba.png

 解决方法:使得跳跃到达的位置与目标位置的差为偶数即可

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

int main()
{
	long long q, x, n;
	scanf("%lld", &q);
	while (q--)
	{
		scanf("%lld", &x);
		x = fabs(x);
		n = sqrt(2 * x);
		while (n * (n + 1) / 2 < x)
			n++;
		while ((n * (n + 1) / 2 - x) % 2 != 0)
			n++;
		printf("%lld\n", n);
	}
	return 0;
}

 Peoblem C.数七

905d5c0f5559425395f2f7f84469d2e4.png

 简单查找即可

#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
	long long n;
	int n1;
	bool yo = false;
	scanf("%lld", &n);
	if (n % 7 == 0)
		printf("Yes\n");
	else
	{
		while (n >= 10)
		{
			if (n % 10 == 7)
			{
				yo = true;
				break;
			}
			n = n / 10;
		}
		if (yo == true || n == 7)
			printf("Yes\n");
		else
			printf("No\n");
	}
	return 0;
}

Peoblem D. 宝石

f3bcd115a13c4ca3a6bafb2562972b5d.png

 解决方法:枚举对称轴与对称半径即可

#include<iostream>
const int N = 5010;
using namespace std;
int main()
{
	int v[N], w[N];
	int n;
	int sum1 = 0, d, sum2, ans = 0, l, r;
	double k;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%d", &v[i]);
	for (int i = 1; i <= n; i++)
		scanf("%d", &w[i]);
	for (int i = 1; i <= n; i++)
	{
		sum1 += v[i] * w[i];
		d = sum2 = 0;
		for (int j = 1; j <= n / 2; ++j)
		{
			if (i - j < 1 || i + j > n)
				break;
			l = i - j;
			r = i + j;
			sum2 += v[l] * w[l] + v[r] * w[r];
			d += v[l] * w[r] + v[r] * w[l];
			ans = max(ans, d - sum2);
		}
		sum2 = d = 0;
		for (int j = 1; j <= n / 2; ++j)
		{
			if (j > i || i + j > n)
				break;
			l = i - j + 1;
			r = i + j;
			sum2 += v[l] * w[l] + v[r] * w[r];
			d += v[l] * w[r] + v[r] * w[l];
			ans = max(ans, d - sum2);
		}
	}
	printf("%d", sum1 + ans);
	return 0;
}

Peoblem E. 最短子序列

574c88ed7b0b4c2b8508b2484b1b9e50.png

 解决方法:枚举左右边界即可

如L[r]与l的差值为左半边的区间大小

R[l]与r的差值为右半边区间的大小

#include<iostream>
using namespace std;
const int N = 1e6 + 10;
const int inf = 0x3f3f3f3f;
int L[N], Rmin[N], R[N];
int a[N];
int main()
{
	int n;
	long long k;
	scanf("%d %lld", &n, &k);
	for (int i = 1; i <= n; ++i)
	{
		scanf("%d", &a[i]);
	}
	int l = 1;
	int sum1 = 0;
	for (int r = 1; r <= n; ++r)
	{
		sum1 += a[r];
		while (l <= r && sum1 - a[l] >= k)
			sum1 -= a[l++];
		if (l <= r && sum1 == k)
			L[r] = l;
		else
			L[r] = -inf;
	}
	int r = n;
	sum1 = 0;
	Rmin[n + 1] = inf;
	for (int l = n; l >= 1; --l)
	{
		sum1 += a[l];
		while (l <= r && sum1 - a[r] >= k)
			sum1 -= a[r--];
		if (l <= r && sum1 == k)
			R[l] = r;
		else
			R[l] = inf;

		Rmin[l] = min(Rmin[l + 1], R[l] - l + 1);
	}
	int ans = inf;
	for (int i = 1; i <= n; ++i)
		ans = min(ans, i - L[i] + 1 + Rmin[i + 1]);
	if (ans > n)
		ans = -1;
	printf("%d", ans);
	return 0;
}

Peoblem F. 分糖果

d676dd57d1124397b92a9388926882b7.png

解决方法:只需要知道糖果多出来的部分与不够的部分总和,再知道可以多分的糖果与可以要糖果的部分总值即可解决

#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
	int n, k, l1, l2, l = -1;
	long cnt = 0, sum1 = 0, sum2 = 0, h1 = 0, h2 = 0;
	bool y = false;
	scanf("%d %d", &n, &k);
	for (int i = 1; i <= n; i++)
	{
		y = false;
		scanf("%d %d", &l1, &l2);
		if (l1 > k)
		{
			sum1 += l1 - k;//缺
		}
		else if (l2 < k)
		{
			h1 += k - l1 + (l2 - k);//h1代表可以多出
		}
		else
			h1 += k - l1;
		if (l2 < k)
		{
			sum2 += k - l2;//多
		}
		else
			h2 += l2 - k;//h2代表可以放入
		if (y == true)
		{
			h2 += k - l1;
		}
	}
	cnt = sum2;
	if (sum2 == sum1)
	{
		printf("%ld\n", cnt);
	}
	else if (sum2 > sum1)
	{
		if (h2 >= sum2 - sum1)
		{
			printf("%ld\n", cnt);
		}
		else
			printf("%d\n", l);
	}
	else
	{
		if (h1 >= sum1 - sum2)
		{
			cnt = sum1;
			printf("%ld\n", cnt);
		}
		else
			printf("%d\n", l);
	}
	return 0;
}

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wby__&&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值