高精,超“实用”!
-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;
}
Blog by cloud_eve is licensed under CC BY-NC-SA 4.0