高精,超“实用”!

发布时间 2024-01-07 16:44:09作者: cloud_eve

-1. 你可以水的题

这些代码可以帮你通过:

0. 导言

在一些毒瘤题中,正常的运算是不满足数据范围的。所以这些时候,就需要高精了。

绝大多数高精的原理,都是进行模拟。如高精加,就是模拟了竖式的计算过程。

1. 高精加高精

如上文所说,模拟了竖式的计算过程。

注意高精运算时需要去除可能的前导零。

#include <bits/stdc++.h>
using namespace std;
const int N = 205;
char s1[N], s2[N];
int a[N], b[N], c[N];
int main() {
	scanf("%s %s", s1, s2);
	int len1 = strlen(s1);
	for (int i = 0; i < len1; i++)
		a[i] = s1[len1 - i - 1] - '0';
	int len2 = strlen(s2);
	for (int i = 0; i < len2; i++)
		b[i] = s2[len2 - i - 1] - '0';
	int sum = 0;
	int len = max(len1, len2) + 1;
	for (int i = 0; i < len; i++) {
		c[i] = a[i] + b[i] + sum;
		sum = c[i] / 10;
		c[i] %= 10;
	}
	for (int i = len - 1; i >= 0; i--) {
		if (0 == c[i] && len > 1) len--;
		else break;
	}
	for (int i = len - 1; i >= 0; i--)
		printf("%d", c[i]);
	printf("\n");
	return 0;
}

2. 高精减高精

同上。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5;
char s1[N], s2[N], tmp[N];
int a[N], b[N], c[N];
int main() {
	scanf("%s %s", s1, s2);
	int len1 = strlen(s1), len2 = strlen(s2);
	if ((len1 < len2) || (len1 == len2 && strcmp(s1, s2) < 0)) {
		printf("-");
		strcpy(tmp, s1), strcpy(s1, s2), strcpy(s2, tmp);
		len1 = strlen(s1), len2 = strlen(s2);
	}
	for (int i = 0; i < len1; i++)
		a[i] = s1[len1 - i - 1] - '0';
	for (int i = 0; i < len2; i++)
		b[i] = s2[len2 - i - 1] - '0';
	for (int i = 0; i < len1; i++) {
		if (a[i] < b[i]) {
			a[i + 1]--;
			a[i] += 10;
		}
		c[i] = a[i] - b[i];
	}
	for (int i = len1 - 1; i >= 0; i--) {
		if (0 == c[i] && len1 > 1) len1--;
		else break;
	}
	for (int i = len1 - 1; i >= 0; i--)
		printf("%d", c[i]);
	printf("\n");
	return 0;
}

3. 高精乘高精

同上和上上。

#include <bits/stdc++.h>
using namespace std;
const int N = 205;
char s1[N], s2[N];
int a[N], b[N], c[2 * N];
int main() {
	scanf("%s %s", s1, s2);
	bool flaga = 0;
	if ('-' == s1[0]) {
		flaga = 1;
		strcpy(s1, &s1[1]);
	}
	bool flagb = 0;
	if ('-' == s2[0]) {
		flagb = 1;
		strcpy(s2, &s2[1]);
	}
	if ((1 == flaga && 0 == flagb) || (0 == flaga && 1 == flagb))
		printf("-");
	int lena = strlen(s1);
	for (int i = 0; i < lena; i++)
		a[lena - i - 1] = s1[i] - '0';
	int lenb = strlen(s2);
	for (int i = 0; i < lenb; i++)
		b[lenb - i - 1] = s2[i] - '0';
	int sum;
	for (int i = 0; i < lena; i++) {
		sum = 0;
		for (int j = 0; j < lenb; j++) {
			c[i + j] = a[i] * b[j] + sum + c[i + j];
			sum = c[i + j] / 10;
			c[i + j] %= 10;
		}
		c[i + lenb] = sum;
	}
	int lenc = lena + lenb;
	for (int i = lenc - 1; i >= 0; i--) {
		if (0 == c[i] && lenc > 1) lenc--;
		else break;
	}
	for (int i = lenc - 1; i >= 0; i--)
		printf("%d", c[i]);
	printf("\n");
	return 0;
}

4. 高精除低精

同上和上上和上上上。

#include <bits/stdc++.h>
using namespace std;
const int N = 205;
int main() {
	char a1[N];
	int a[N], ans[N], len1, rm = 0, len = 1, b;
	gets(a1);
	scanf("%d", &b);
	len1 = strlen(a1);
	for (int i = 1; i <= len1; i++)
		a[i] = a1[i - 1] - 48;
	for (int i = 1; i <= len1; i++) {
		ans[i] = (rm * 10 + a[i]) / b;
		rm = (rm * 10 + a[i]) % b;
	}
	while (ans[len] == 0 && len != len1)
		len++;
	for (int i = len; i <= len1; i++)
		printf("%d", ans[i]);
	return 0;
}

5. 高精除高精

同上和上上和上上上和上上上上。

#include <bits/stdc++.h>
using namespace std;
const int N = 205;
char s1[N], s2[N], tmp[N];
int a[N], b[N], c[N];
int compare(int a[], int b[]) {
	if (a[0] > b[0]) return 1;
	else if (a[0] < b[0]) return -1;
	for (int i = a[0]; i > 0; i--) {
		if (a[i] > b[i]) return 1;
		else if (a[i] < b[i]) return -1;
	}
	return 0;
}
void numcpy(int a[], int b[], int dest) {
	for (int i = 1; i <= a[0]; i++)
		b[i + dest - 1] = a[i];
	b[0] = a[0] + dest - 1;
}
int main() {
	scanf("%s %s", s1, s2);
	bool flag1 = 0;
	if ('-' == s1[0]) {
		flag1 = 1;
		strcpy(s1, &s1[1]);
	}
	bool flag2 = 0;
	if ('-' == s2[0]) {
		flag2 = 1;
		strcpy(s2, &s2[1]);
	}
	if (1 == flag1 && 0 == flag2) printf("-");
	int len = strlen(s1);
	a[0] = len;
	for (int i = 0; i < len; i++)
		a[len - i] = s1[i] - '0';
	len = strlen(s2);
	b[0] = len;
	for (int i = 0; i < len; i++)
		b[len - i] = s2[i] - '0';
	if (0 == compare(a, b)) {
		printf("1\n0\n");
		return 0;
	} else if (-1 == compare(a, b)) {
		printf("0\n");
		if (1 == flag1) printf("-");
		printf("%s\n", s1);
		return 0;
	} else {
		c[0] = a[0] - b[0] + 1;
		for (int i = c[0]; i > 0; i--) {
			memset(tmp, 0, sizeof(tmp));
			numcpy(b, tmp, i);
			while (compare(a, tmp) >= 0) {
				c[i]++;
				for (int j = 1; j <= a[0]; j++) {
					if (a[j] < tmp[j]) 
						a[j + 1]--, a[j] += 10;
					a[j] -= tmp[j];
				}
				int k = a[0];
				while (a[k] == 0) k--;
				a[0] = k;
			}
		}
		while (c[0] > 0 && c[c[0]] == 0) c[0]--;
	}
	for (int i = c[0]; i > 0; i--)
		printf("%d", c[i]);
	printf("\n");
	if (0 == a[0]) printf("0\n");
	else {
		if (1 == flag1) printf("-");
		for (int i = a[0]; i > 0; i--)
			printf("%d", a[i]);
		printf("\n");
	}
	return 0;
}

6. 高精快速幂

#include <bits/stdc++.h>
using namespace std;
const int mod = 10, N = 1e5 + 5;
int p;
int a[N], b[N], c[N];
void mul(int a[], int b[]) {
	memset(c, 0, sizeof(c));
	for (int i = 1; i <= a[0]; i++)
		for (int j = 1; j <= b[0]; j++) {
			c[i + j - 1] = c[i + j - 1] + a[i] * b[j];
			if (i + j - 1 > c[0]) c[0] = i + j - 1;
		}
	for (int i = 1; i <= c[0]; i++)
		if (c[i] / mod) {
			c[i + 1] = c[i + 1] + c[i] / mod;
			c[i] %= mod;
			if (i + 1 > c[0]) c[0] = i + 1;
		}
	int l = max(c[0], b[0]);
	for (int i = 0; i <= l; i++) b[i] = c[i];
}
void add(int a[], int b[]) {
	int l = max(a[0], b[0]);
	for (int i = 1; i <= l; i++) {
		b[i] += a[i];
		if (b[0] < i) b[0] = i;
	}
	for (int i = 1; i <= b[0]; i++) {
		if (b[i] / mod) {
			b[i + 1] = b[i + 1] + b[i] / mod;
			b[i] %= mod;
			if (b[0] < i + 1) b[0] = i + 1;
		}
	}
}
void cut(int a[], int x) {
	a[1] -= x;
	for (int i = 1; i <= a[0]; i++) {
		if (a[i] < 0) {
			a[i] += mod, a[i + 1]--;
			if (a[0] == i + 1 && !a[i + 1]) a[0]--;
		}
	}
}
void mul_d(int b[], int x) {
	for (int i = 1; i <= b[0]; i++) b[i] *= x;
	for (int i = 1; i <= b[0]; i++) {
		if (b[i] / mod) {
			b[i + 1] = b[i + 1] + b[i] / mod;
			b[i] %= mod;
			if (i + 1 > b[0]) b[0] = i + 1;
		}
	}
}
void fast_poww(int p) {
	b[0] = 1, b[1] = 2;
	a[0] = 1, a[1] = 1;
	while (p) {
		if (p & 1) mul(b, a);
		p >>= 1;
		mul(b, b);
	}
}
int main() {
	scanf("%d", &p);
	fast_poww(p);
	cut(a, 1);
	int ans = a[0];
	printf("%d\n", ans);
	for (int i = 1; i <= 10; i++) {
		for (int j = 1; j <= 50; j++)
			printf("%d", a[500 - (i - 1) * 50 - (j - 1)]);
		putchar('\n');
	}
	return 0;
}

7. 高精 gcd

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, m, k, a[N], b[N], G[N], sol[N];
char s1[N], s2[N];
inline int minn(int x, int y) {
	return x < y ? x : y;
}
inline bool check() {
	if ((n == 1 && a[1] == 0) || (m == 1 && b[1] == 0)) return 0;
	return 1;
}
inline void print(int*x, int len) {
	for (int i = len; i >= 1; i--)
		putchar(x[i] ^ 48);
}
inline void llmul(int*x, int&len) {
	bool flag = 0;
	for (int i = 1; i <= len; i++) {
		x[i] <<= 1;
		if (flag) x[i] |= 1;
		if (x[i] >= 10) x[i] -= 10, flag = 1;
		else flag = 0;
	}
	if (flag) {
		len++;
		x[len] = 1;
	}
}
inline void lldiv(int*x, int&len) {
	int num = 0, ans[N];
	for (int i = len; i >= 1; i--) {
		if (x[i] & 1) {
			int now = ((num * 10 + x[i]) >> 1) << 1;
			ans[i] = (num * 10 + x[i]) >> 1;
			num = (num * 10 + x[i]) - now;
		} else {
			ans[i] = (num * 10 + x[i]) >> 1;
			num = 0;
		}
	}
	for (int i = len; i >= 1; i--) {
		if (ans[i] == 0) len--;
		else break;
	}
	if (len == 0) len++;
	for (int i = 1; i <= len; i++)
		x[i] = ans[i];
	return ;
}
inline bool cmp() {
	if (n < m) return 0;
	if (n > m) return 1;
	for (int i = n; i >= 1; i--) {
		if (a[i] < b[i]) return 0;
		else if (a[i] > b[i]) return 1;
	}
	return 1;
}
inline void solve(int*x, int&l1, int*y, int l2) {
	for (int i = 1; i <= l2; i++) {
		x[i] -= y[i];
		if (x[i] < 0) --x[i + 1], x[i] += 10;
	}
	if (l1 == 1) return ;
	while (l1 > 0 && x[l1] == 0) --l1;
	if (l1 == 0) l1 = 1;
	return ;
}
inline void change(int*x, int&l1, int*y, int l2) {
	l1 = l2;
	for (int i = 1; i <= l1; i++) x[i] = y[i];
	return ;
}
int len, cnt;
int main() {
	scanf("%s%s", s1 + 1, s2 + 1);
	n = strlen(s1 + 1), m = strlen(s2 + 1);
	G[++k] = 1;
	for (int i = 1, j = n; i <= n; i++, j--) a[j] = s1[i] - '0';
	for (int i = 1, j = m; i <= m; i++, j--) b[j] = s2[i] - '0';
	while (check()) {
		if (a[1] % 2 == 0 && b[1] % 2 == 0)
			lldiv(a, n), lldiv(b, m), ++cnt;
		else if (a[1] % 2 == 0 && (b[1] & 1)) lldiv(a, n);
		else if ((a[1] & 1) && b[1] % 2 == 0) lldiv(b, m);
		else {
			if (!cmp()) solve(b, m, a, n);
			else solve(a, n, b, m);
		}
	}
	if (cmp()) change(sol, len, a, n);
	else change(sol, len, b, m);
	for (int i = 1; i <= cnt; i++) llmul(sol, len);
	print(sol, len);
	return 0;
}