算法学习-模拟与高精度

通用模板(vector版本)

1.加减

#include<bits/stdc++.h>
using namespace std;
vector<int >A, B;
bool cmp(vector<int >& A, vector<int >& B)//比较
{
	if (A.size() != B.size())return A.size() > B.size();
	else
	{
		for (int i = A.size() - 1; i >= 0; i--)
		{
			if (A[i] != B[i])return A[i] > B[i];
		}
		return true;
	}
}
vector<int> add(vector<int >& A, vector<int >& B)//加法
{
	vector<int>C;
	int t = 0;
	for (int i = 0; i < A.size() || i < B.size(); i++)
	{
		if (i < A.size())t += A[i];
		if (i < B.size())t += B[i];
		C.push_back(t % 10);
		t /= 10;
	}
	if (t)C.push_back(1);
	return C;
}
vector<int> sub(vector<int >& A, vector<int >& B)//减法,注意这里A是大于B的
{
	vector<int>C;
	int t = 0;
	for (int i = 0; i < A.size(); i++)
	{
		t = A[i] - t;
		if (i < B.size())t -= B[i];
		C.push_back((t + 10) % 10);
		if (t < 0)t = 1;
		else t = 0;
	}
	while (C.size() > 1 && C.back() == 0)C.pop_back();
	return C;
}
int main()
{
	string a, b;
	cin >> a >> b;
	for (int i = a.size() - 1; i >= 0; i--)A.push_back(a[i] - '0');
	for (int i = b.size() - 1; i >= 0; i--)B.push_back(b[i] - '0');
	bool flag = 0;
	if (!cmp(A,B))
	{
		flag = true;
		swap(A, B);
	}
	auto add_ans = add(A, B);
	for (int i = add_ans.size() - 1; i >= 0; i--)
	{
		cout << add_ans[i];
	}
	cout << endl;
	auto sub_ans = sub(A, B);
	for (int i = sub_ans.size() - 1; i >= 0; i--)
	{
		if (flag && i == sub_ans.size() - 1)cout << '-';
		cout << sub_ans[i];
	}
	cout << endl;
	return 0;
}

2.乘除

#include<bits/stdc++.h>
using namespace std;
vector<int>mul(vector<int>& A, int b)//乘法
{
	vector<int >C;
	int t = 0;
	for (int i = 0; i < A.size() || t; i++)
	{
		if (i < A.size())
		{
			t += A[i] * b;
		}
		C.push_back(t % 10);
		t /= 10;
	}
	return C;
}
vector<int>div(vector<int>& A, int &b,int &t)//除法
{
	vector<int>C;
	t = 0;
	for (int i = A.size() - 1; i >= 0; i--)
	{
		t = t * 10 + A[i];
		C.push_back(t /b);
		t%=b;
	}
	reverse(C.begin(), C.end());//为和加减乘除保持一致
	while (C.size() > 1 && C.back() == 0)C.pop_back();
	return C;
}
int main()
{
	int b;
	string a;
	vector<int>A;
	cin >> a >> b;
	for (int i = a.size() - 1; i >= 0; i--)A.push_back(a[i]- '0');
	auto mul_ans = mul(A, b);
	for (int i = mul_ans.size()-1; i >= 0; i--)
	{
		cout << mul_ans[i];
	}
	int t;//代表余数
	auto div_ans = div(A, b,t);
	for (int i = div_ans.size() - 1; i >= 0; i--)
	{
		cout << div_ans[i];
	}
	cout << endl << t << endl;
}

高精度

首先引入一篇较好的文章来了解什么是高精度,以及高精度基本的运算(加减乘除)。

https://blog.csdn.net/fanyun_01/article/details/79967170

以及一道简单的入门题目

 以及本人代码

#include<bits/stdc++.h>
using namespace std;
int a[10000], b[10000], ans[10000];
int main() {
	string A, B;
	cin >> A >> B;
	int len_A, len_B;
	len_A = A.length();
	len_B= B.length();//位数储存
	for (int i = 1; i <=len_A; i++) {
		a[i] = A[len_A - i] - '0';//注意A是由A[0]开始的
	}
	for (int i = 1; i <=len_B; i++) {
		b[i] = B[len_B - i] - '0';
	}//现在a,b已经变为倒序,为方便后续的进位
	int len =(len_A>len_B?len_A:len_B);//确定最长位数
	for (int i = 1; i <= len; i++) {
		ans[i] += a[i] + b[i];//注意是+=而不是=,因为一开是有可能因为有进位的而有初值
		ans[i + 1] += (ans[i] / 10);//进位
		ans[i] %= 10;//保留个位
	}
	len++;
	if((ans[len] == 0) && (len > 1))len--;//如果有0,去掉最高位的0,如果是其他值,则保留
	for (int i = len; i >= 1; i--) {
		cout << ans[i];
	}
	return 0;
}

以及一道高精度加低精度,高精度乘以高精度以及高精度除以低精度的综合运用

         AC代码(运用高斯公式简化计算)

#include<iostream>
#include<string.h>
using namespace std;
#define max 202
int a[max], b[max], c[max];
int main()
{
	string s;
	cin >> s;
	int x, i, j;
	int len = s.size();
	for (int i = 0; i < len; i++) {
		a[len - i] = s[i] - '0';
		b[len - i] = s[i] - '0';
	}//注意这个是len-i,则最小一项为1
	b[1]++;//首项加末相
	for (int i = 1; i <= len; i++) {
		if (b[i] == 10) {
			b[i] = 0;
			b[i + 1]++;
		}//进位
		else break;
	}
	int len_B = len + 1;
	while (b[len_B] == 0 && len_B > 1)len_B--;//防止出现999之类的数据
	//高精度乘法
	for (int i = 1; i <= len_B; i++) {
		x = 0;
		for (int j = 1; j <= len; j++) {
			c[i + j - 1] += a[j] * b[i] + x;//建议写一个比较小的俩位数相乘来方便理解,x用来表示进位
			x = c[i + j - 1] / 10;
			c[i + j - 1] %= 10;
		}//注意最后赋值的是i+len-1,i+len(j=len时候)没有得到进位数值,则下面补充
		c[i + len] = x;
	}//c此时是正序
	int lenc = len+len_B+1;
	while (c[lenc] == 0 && lenc > 1)lenc--;
	for (int i = lenc; i >= 1; i--) {
		if (c[i] % 2 == 0) {
			c[i] /= 2;
		}
		else {
			c[i - 1] += 10;
			c[i] /= 2;
		}
	}
	while (c[lenc] == 0 && lenc > 1)  lenc--;//去除前面的0
	for (int i = lenc; i >= 1; i--) {
		cout << c[i];
	}
}

以及一个刚开始写的超时代码

#include<bits/stdc++.h>
using namespace std;
int a[10005];//1表示个位,2表示十位依次类推
int main() {
	int n; cin >> n;
	int len=1, temp;//len表示目前的位数,temp用于进位
	a[1] = 1;//对初始对象赋值
	for (int i = 2; i <= n; i++) {
		temp = 0;//重置
		for (int j = 1; j <= len; j++) {
			if (j == 1) {
				a[j] += i + temp;
				temp = a[j] / 10;
				a[j] %= 10;
			}//一开始对个位的操作
			else {
				a[j] += temp;//后面位数改变靠前面一位进位实现
				temp = a[j] / 10;
				a[j] %= 10;
			}
		}
		if (temp != 0)a[++len] = temp;//表示进过位,说明总位数len发生了改变
	}
	for (int i = len; i >= 1; i--)cout << a[i];//倒叙输出
	cout << endl;
	return 0;
}//时间复杂度太高,超时!

以及一个补充题目有兴趣的可以去洛谷写写(这道题主要是对于未知位数的处理,思想很独到值得一些)

 以及本人代码

#include<bits/stdc++.h>
using namespace std;
int a[150], ans[150];
int main() {
	int n,count=100;
	cin >> n;
	a[1] = ans[1] = 1;//a用来储存n-1的阶乘
	for (int i = 2; i <= n; i++) {
		for (int j = 1; j <= 100; j++) {//最多不超过100位,当然也可以再定大一些
//不过尽量看看代码规定时长不要超时
			a[j] *= i;//作乘法,给每一项相乘
		}
		for (int j = 1; j <= 100; j++) {
			if (a[j] > 9) {
				a[j + 1] += a[j] / 10;//进位
				a[j] %= 10;
			}
		}
		for (int j = 1; j <= 100; j++) {
			ans[j] += a[j];
			for (int j = 1; j <= 100; j++) {
				if (ans[j] > 9) {
					ans[j + 1] += ans[j] / 10;//进位
					ans[j] %= 10;
				}
			}
		}
	}
	while (ans[count] == 0)count--;//对多余位数进行消去
	for (int i = count; i >= 1; i--) {
		cout << ans[i];
	}
	return 0;
}

模拟

一道简单题来引入(https://www.luogu.com.cn/problem/P1042

 本人代码

#include<bits/stdc++.h>
using namespace std;
char ans[100];
int main()
{
	char a;
	
	int W=0, L=0;
	int count = 0;
	while ((a=getchar()))
	{ 
		if (a == 'E') {
			cout << W << ":" << L << endl;
			break;
		}
		if (a == '/n')continue;//防止空格被记录
		ans[++count] = a;//从1开始计数,并且不会记录E
		if (a == 'W')W++;
		else if (a == 'L')L++;//abs() fabs()分别可以对整型和浮点型求绝对值
		if (W >= 11 && W - L >= 2||L>=11&&L-W>=2) {
			cout << W << ":" << L << endl;
			W = 0, L = 0;
		}
	}
	W = 0, L = 0;//归零
	cout << endl;
	for (int i = 1; i <= count; i++) {
		if (ans[i] == 'W')W++;
		else if (ans[i] == 'L')L++;
		if (W >= 21 && W - L >= 2 || L >= 21 && L - W >= 2) {
			cout << W << ":" << L << endl;
			W = 0, L = 0;
		}
	}
	if (W != 0 || L != 0)cout << W << ":" << L << endl;
	return 0;
}

其中比较值得借鉴的是对于空格细节的处理,以及对有特定终止符号的字符串如何读取和储存。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值