第一周双周赛

目录

第一道题

思路:  这是一个比较基础的模拟题,就是先标记,后扫描就完事了

AC代码:

第二题:

 思路:

AC代码:

第三道题:

思路:

AC代码:

第四题

解题思路:

AC代码

第五题:

 思路:

这道题我用的是暴力法毕竟区间和两根的距离的最小值都已经给出来了,没啥好说的,不过有一点细节是,找出三个根后可以直接break掉,减少代码所需要的时间

AC代码:


第一道题

思路:
  这是一个比较基础的模拟题,就是先标记,后扫描就完事了

AC代码:

#include<bits/stdc++.h>
using namespace std;
int b[1005];
int main() {
	int n; cin >> n;
	string a;
	cin >> a;
	for (int i = 0; i < n; i++) {
		if (a[i] == 'L')b[i] = 1;
	}
	for (int i = 0; i < n; i++) {
		if (i == 1) {
			if (b[i + 1] != 1 && b[i] != 1) {
				b[i] = 2;
			}
		}
		else {
			if(b[i + 1] != 1 && b[i] != 1 && b[i - 1] != 1)b[i] = 2;
		}
	}
	for (int i = 0; i < n; i++) {
		if (b[i] == 1)cout << "L";
		else if (b[i] == 2)cout << "C";
		else cout << ".";
	}
	return 0;
}

第二题:

 思路:

是一个比较基础的高精度题,但是需要知道十进制和十六进制如何转化,以及后续统一进位的技巧

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+5;
int a[N], b[N], ans[2*N+5];
int main() {
	string A, B;
	cin >> A >> B;
	int len_A = A.size(), len_B = B.size();
	for (int i = 1; i <= len_A; i++) {
		if (A[len_A - i] >= 'A')a[i] = A[len_A - i] - 'A' + 10;
		else a[i] = A[len_A - i]-'0';
	}
	for (int i = 1; i <= len_B; i++) {
		if (B[len_B - i] >= 'A')b[i] = B[len_B - i] - 'A' + 10;
		else b[i] = B[len_B - i] - '0';
	}//倒序
	for (int i = 1; i <= len_A; i++) {
		for (int j = 1; j <= len_B; j++) {
			ans[i + j - 1] += a[i] * b[j];
		}
	}//先不进位,后续方便转化回16进制
	int len = len_A + len_B + 5;
	for (int i = 1; i <= len; i++) {
		if (ans[i] >= 16) {
			ans[i + 1] += ans[i] / 16;
			ans[i] %= 16;
		}
	}
	while (ans[len] == 0 && len > 1)len--;
	for (int i = len; i >= 1; i--) {
		if (ans[i] > 9) {
			if (ans[i] == 10)cout << "A";
			else if (ans[i] == 11)cout << "B";
			else if (ans[i] == 12)cout << "C";
			else if (ans[i] == 13)cout << "D";
			else if (ans[i] == 14)cout << "E";
			else if (ans[i] == 15)cout << "F";
		}
		else cout << ans[i];
	}
	return 0;
}

第三道题:

 

思路:

这道题主要是引入一个时间变量time来简化判断,将移动的过程化为时间的增加

AC代码:

#include<bits/stdc++.h>
using namespace std;
int n, m;
int a[100005];
bool check(int x) {
	int now = 1, time = 0;//敌人移动的距离和时间相同(v=1)
	while (now<=n)
	{
		if (a[now] < time)return false;//移动的距离大于一开始距离小明的距离,则说明小明被杀了,该情况不符合条件
		if (a[now]-time > m) {//前面有可能有时间累加,则需要算上移动的时间
			time += (a[now] - time - m);//如果敌人在射程外,先让他过来,瞬移
		}
		now++;//上一个敌人已经被杀,开始计算下一个敌人
		time += x;//加上换弹的时间
	}
	return true;
}
int main() {
	 cin >> n >> m;
	int count = 0;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	sort(a + 1, a + 1 + n);
	int left = 1, right = a[n], mid, ans;//排除只有俩个人,且第一个的一开始距离1m,另外一个人距离9999999m的边缘数据
	while (left<right)
	{
		mid = (left + right) / 2;
		if (check(mid)) { 
		left = mid + 1; 
		ans = max(ans, mid);
		}
		else right = mid - 1;
	}
	cout << ans << endl;
	return 0;
}

第四题

 

解题思路:
 

用数组下标来表示结点位置,从而方便的表示对应位置的结点。
将链表以K为界划分为若干子链,将每个子链反转,然后衔接左右的子链。
反转子链的方法:用head和tail头尾指针,分别指向待反转子链的头尾,固定tail不动,将头依次插到tail后面(期间要多用到一个p指针记录位置 )。
注意:
给出的结点不一定所有的结点都是链表的成员结点(可能有多余结点)。
中间的子链要衔接上一个子链的尾,也要衔接下一个子链的头 。
需要考虑到的情况:如果K=1,链表不反转;如果K等于链表的节点数,链表整个反转;如果链表的节点数能被K整除,则每段都要反转。
 

AC代码

#include<bits/stdc++.h>
using namespace std;
#define MaxSize 100000
struct Node {      //存放结点数据 
	int Data;
	int NextAdd;
}A[MaxSize];       //数组A定义为了全局变量,模拟真实的内存环境 
int Reverse(int Head, int times, int K);
int Count(int head);
int main()
{
	int Head, N, K, Add;
	cin >> Head >> N >> K;//Head首地址,一共有N个节点,每K个数字反转,不足K个则按照原数据输出
	for (int i = 0; i < N; i++) {			//读入数据 
		cin >> Add >> A[Add].Data >> A[Add].NextAdd;//表示地址
	}
	int times = Count(Head) / K;		//需要知道执行几次反转操作,否则多次反转无法实现 
	int New = Reverse(Head, times, K);	//进行反转 
	int p =New;
	while (p != -1) {
		if (A[p].NextAdd != -1)  //输出格式控制 
			printf("%05d %d %05d\n", p, A[p].Data, A[p].NextAdd);
		else
			printf("%05d %d %d\n", p, A[p].Data, A[p].NextAdd);
		p = A[p].NextAdd;
	}					//打印结果 
	return 0;
}
int Reverse(int Head, int times, int K)
{
	int New, TmpNew, Old, Tmp, Tail, cnt;	//New,TmpNew,Old,Tmp,Tail均起到指针的作用;cnt是计数器 
	for (int i = 0; i < times; i++) {
		cnt = 1;							//初始化
		TmpNew = Head;//标记一下为(1)
		Old = A[TmpNew].NextAdd;
		while (cnt < K) {					//依次反转 
			Tmp = A[Old].NextAdd;//相当于由原来的1->2->3,2的下一个地址变为1
			A[Old].NextAdd = TmpNew;		//反转操作 
			TmpNew = Old;//这一步相当于上面标记的1
			Old = Tmp;
			cnt++;
		}
		A[Head].NextAdd = Old;			//反转后的尾巴连接到下一个头结点 
		if (i == 0) {						//第一次反转的TmpNew是真正的New
			New = TmpNew;
		}
		else {
			A[Tail].NextAdd = TmpNew;		//需要把上次反转的尾巴的Next指针指到TmpNew
		}
		Tail = Head;
		Head = Old;
	}
	return New;
}
int Count(int head)		//统计链表的真实结点数目 
{
	int sum, p;
	p = head, sum = 0;
	while (p !=-1) {
		sum++;
		p = A[p].NextAdd;
	}
	return sum;
}

第五题:

 思路:

这道题我用的是暴力法毕竟区间和两根的距离的最小值都已经给出来了,没啥好说的,不过有一点细节是,找出三个根后可以直接break掉,减少代码所需要的时间

AC代码:

#include<bits/stdc++.h>
using namespace std;
double a, b, c, d, p, q;
double F(double x) {
	return a * x * x * x + b * x * x + c * x + d;
}
int main() {
	int n; cin >> n;
	int count = 0;
	for (int i = 0; i < n; i++) {
		cin >> a >> b >> c >> d >> p >> q;
		for (double i = p; i <= q; i += 1e-6) {
			double j = i + 1e-6;
			if (F(i) * F(j) < 0) {
				double mid = (i + j) / 2;
				cout << fixed << setprecision(6) << mid << " ";
				count++;
			}
			if (count == 3)break;
		}
	}
	return 0;
}

参考文章:(41条消息) 【链表】Reversing Linked List_墨客T的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值