指针原来是套娃的


私信TA

用户名:uq_92467646842

访问量:52318

签 名:

个人博客:blog.imtwa.top

等  级
排  名 11
经  验 26504
参赛次数 49
文章发表 128
年  龄 0
在职情况 学生
学  校
专  业 物联网工程

  自我简介:

解题思路:
作为比赛的第二道大题 这个还是有点难度的,数据量这么大 就是明摆考察高精度了。2^1000 大概是10的300次方 10e300*10e1024 位数在两千位以内 所以不用考虑内存不够。

这里给出两种解法 一个是使用数组 一个是使用队列。使用数组需要多考虑一下n的边界。

因为有小数的情况,所以需要记录一下小数点的位置(或者说是小数占几位),无论怎么乘小数位是不会变的,因为每次*2 所以整数位最多上进1位。

详见代码:

#include <bits/stdc++.h>
using namespace std;
int A[10010],B = 2;
int n=0;

void mul(int A[]) {
	int t=0; // 用于存储进位
	for(int i=0; i<n; i++) {
		A[i]=(A[i]*B) + t;
		t=A[i]/10;
		A[i]%=10;
	}
	// 如果有进位
	if(t!=0) {
		A[n]=t;
		n++;
	}
}

int main() {
	int N;
	scanf("%d",&N); // 输入需要乘以的次数
	string s;
	cin>>s; // 输入浮点数

	int flag=0;
	for(int i=s.size()-1; i>=0; i--) {
		if(s[i]=='.') {
			flag=s.size()-1-i; // 记录小数点的位置
			continue;
		} else {
			A[n]=(s[i]-'0');
			n++;
		}
	}

	while(N--) {
		mul(A); // 执行乘法操作
	}
	// 注意 此时为倒序储存 3.14为413 所以起始位i=n-1 十分位为 flag-1(数组有下标0)
	// 判断是否需要四舍五入
	if(A[flag-1]>=5) {
		int t=1; // 末尾+1 注意i=flag 
		for(int i=flag; i<n; i++) {
			A[i]=A[i]+t;
			t=A[i]/10;
			A[i]%=10;
		}

		if(t!=0) {
			A[n]=t;
			n++;
		}
	}
	// 直接打印
	for(int i=n-1; i>=flag; i--) {
		cout<<A[i];
	}

	return 0;
}


解法二:

使用stl库里面的队列 有队列就不用考虑n的位置问题 不过不能像数组一样直接获得十位数判断四舍五入。

#include <bits/stdc++.h> 
using namespace std;

// 用于模拟大整数的乘法,每次乘以2
void mul(vector<int> &ver) {
	int t=0; // 用于存储进位
	for(auto &x:ver) {
		x=x*2+t; // 当前位乘以2并加上之前的进位
		t=x/10;  // 计算新的进位
		x=x%10;  // 更新当前位的值
	}
	if(t) ver.push_back(t); // 如果还有进位,则添加到vector的末尾
}

int main() {
	int n;
	scanf("%d",&n); // 输入需要乘以的次数
	string s;
	cin>>s; // 输入浮点数
	reverse(s.begin(),s.end()); // 反转字符串,这样小数的处理会变得更简单

	vector<int> ver; // 存储每一位的整数值
	int flag=0;
	for(int i=0; i<s.size(); i++) {
		if(s[i]=='.') {
			flag=i; // 记录小数点的位置
			continue;
		} else {
			ver.push_back(s[i]-'0'); // 将字符转换为数字并添加到vector中
		}
	}

	while(n--) {
		mul(ver); // 执行乘法操作
	}

	reverse(ver.begin(),ver.end()); // 再次反转,恢复原始顺序

	int bak=-1;
	while(flag--) {
		bak=ver.back(); // 从小数点开始,逐个移除位
		ver.pop_back();
	}

	// 如果最后一位(被移除的小数部分的最后一位)大于等于5,则进行四舍五入
	if(bak>=5) {
		reverse(ver.begin(),ver.end());
		int flag=1;
		for(int i=0; i<ver.size(); i++) {
			ver[i]+=flag;
			flag=ver[i]/10;
			ver[i]=ver[i]%10;
		}
		if(flag) {
			ver.push_back(flag);
		}
		reverse(ver.begin(),ver.end());
	}

	for(auto x:ver) {
		printf("%d",x); // 输出结果
	}
	return 0;
}



ps:再写一个骗分的代码 就是使用double无视位数问题,double最大可达10的三百多次方 和一千位比起来小了点 但是应该可以过50%的测试点(此代码无法通过全部测试点!!) 不过能得一分是一分。

#include <bits/stdc++.h>
using namespace std;

int main() {
	int n;
	double d;
	cin>>n>>d;
	d = round(pow(2,n)*d);
	printf("%.0lf\n",d);

	return 0;
}


 

0.0分

177 人评分

  评论区

希望double暴力多给点
2024-04-15 10:40:24
  • «
  • 1
  • »