高精(学习)

在这里插入图片描述

Vijos 1040 高精度乘法
Vijos 1257 水王争霸
Vijos 1779 国王游戏

“基础算法”专栏(目录)


更多模板

高精加法:

#include <bits/stdc++.h>

using namespace std;

char str[505];

struct BigNum {
	int num[505], len;
}A, B, C;

void print(BigNum &x) { //输出大整数x 
	for(int i = x.len - 1; i >= 0; i--) printf("%d", x.num[i]);
	printf("\n");
}

void add(BigNum &x, BigNum &y, BigNum &z) {  
	z.len = max(x.len, y.len); // 结果最小长度为两者长度最大值 
	for(int i = 0; i < z.len; i++) z.num[i] = x.num[i] + y.num[i]; // 不进位加法得到初步结果 
	for(int i = 0; i < z.len; i++) 
		if(z.num[i] > 9) { // 进行逐位进位 
			z.num[i + 1] += 1;
			z.num[i] -= 10;
		}
	if(z.num[z.len]) ++z.len; // 判断最高位是否有进位 
}

int main() {
	// 读取并倒序存储大整数A 
	scanf("%s", str);
	int len = strlen(str);
	A.len = len;
	for(int i = 0; i < len; i++) A.num[len - i  - 1] = str[i] - '0';
	// 读取并倒序存储大整数B
	scanf("%s", str);
	B.len = len = strlen(str);
	for(int i = 0; i < len; i++) B.num[len - i  - 1] = str[i] - '0';
	add(A, B, C); // 计算结果 
	print(C); // 输出 
	return 0;
}

高精减法:

#include <bits/stdc++.h>

#define MAXN 11111 
using namespace std;

char str[MAXN];

struct BigNum {
	int num[MAXN], len;
}A, B, C;

void print(BigNum &x) { //输出大整数x 
	for(int i = x.len - 1; i >= 0; i--) printf("%d", x.num[i]);
	printf("\n");
}

int judge(BigNum &x, BigNum &y) { 
	// 比较函数  长度长的大,其次从高到低逐位比较,全相同返回0,x>y返回1, x<y返回-1 
	if(x.len > y.len) return 1;  
	if(x.len < y.len) return -1;
	for(int i = x.len - 1; i >= 0; i--) {
		if(x.num[i] > y.num[i]) return 1;
		if(x.num[i] < y.num[i]) return -1;
	}
	return 0;
}

void Minus(BigNum &x, BigNum &y, BigNum &z) { 
	if(judge(x, y) == -1) {
		printf("-"); 
		Minus(y, x, z); //保证被减数为较大的 
	} else {	
		z.len = x.len; // 结果最小长度为x长度 
		for(int i = 0; i < z.len; i++) z.num[i] = x.num[i] - y.num[i]; // 不进位减法得到初步结果 
		for(int i = 0; i < z.len; i++) 
			if(z.num[i] < 0) { // 进行逐位退位
				z.num[i + 1] -= 1;
				z.num[i] += 10;
			}
		while(z.len > 1 && !z.num[z.len - 1]) --z.len; // 判断最高位是否有退位 
	}
	return ;
}

int main() {
	// 读取并倒序存储大整数A 
	scanf("%s", str);
	int len = strlen(str);
	A.len = len;
	for(int i = 0; i < len; i++) A.num[len - i  - 1] = str[i] - '0';
	// 读取并倒序存储大整数B
	scanf("%s", str);
	B.len = len = strlen(str);
	for(int i = 0; i < len; i++) B.num[len - i  - 1] = str[i] - '0';
	Minus(A, B, C); // 计算结果 
	print(C); // 输出 
	return 0;
}

高精乘低精:

#include <bits/stdc++.h>

#define MAXN 11111 
using namespace std;

char str[MAXN];

struct BigNum {
	int num[MAXN], len;
}A, B, C;

void print(BigNum &x) { //输出大整数x 
	for(int i = x.len - 1; i >= 0; i--) printf("%d", x.num[i]);
	printf("\n");
}

void Multi(BigNum &x, int y, BigNum &z) { 
	z.len = x.len; // 最小长度 
	for(int i = 0; i < z.len; i++) z.num[i] = x.num[i] * y; //逐位相乘 
	for(int i = 0; i < z.len; i++) { // 进位处理 
		z.num[i + 1] += z.num[i] / 10; 
		z.num[i] %= 10;	
		if(i == z.len - 1 && z.num[i + 1]) ++z.len; // 最高位进位 
	}
	return ;
}

int main() {
	// 读取并倒序存储大整数A 
	scanf("%s", str);
	int len = strlen(str);
	A.len = len;
	for(int i = 0; i < len; i++) A.num[len - i  - 1] = str[i] - '0';
	int b;
	scanf("%d", &b);
	Multi(A, b, C); // 计算结果 
	print(C); // 输出 
	return 0;
}

高精乘高精:

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

int main(){
    string as, bs;
    int an[101] = {0}, bn[101] = {0}, c[10200] = {0}, aLen, bLen, cLen;
    
    cin >> as >> bs;
    
    aLen = as.length();
    bLen = bs.length();
    
    //倒序存储两个数于整型数组中 
    for(int i = 0; i < aLen; i ++){
        an[aLen - i - 1] = as[i] - '0';
    }
    
    for(int i = 0; i < bLen; i ++){
        bn[bLen - i - 1] = bs[i] - '0';
    }

    //进行乘法运算,结果存于c[]
    for(int i = 0; i < bLen; i ++) {
        for(int j = 0; j < aLen; j ++) {
            c[i + j] += an[j] * bn[i];
            c[i + j + 1] += c[i + j] / 10;
            c[i + j] %= 10;
        }
    }
     
    cLen = aLen + bLen;
    
    //删除结果高位的前缀0 
    while(c[cLen - 1] == 0 && cLen > 1){
        cLen --;
    }
    
    //将结果倒序输出
    for(int i = cLen - 1; i >= 0; i --){
        cout << c[i];
    }
    
    cout<<endl;
    
    return 0;
}
#include <bits/stdc++.h>

#define MAXN 11111 
using namespace std;

char str[MAXN];

struct BigNum {
	int num[MAXN], len;
}A, B, C;

void print(BigNum &x) { //输出大整数x 
	for(int i = x.len - 1; i >= 0; i--) printf("%d", x.num[i]);
	printf("\n");
}

void Multi(BigNum &x, BigNum &y, BigNum &z) { 
	z.len = x.len + y.len; // 最大长度 
	for(int i = 0; i < x.len; i++)
		for(int j = 0; j < y.len; j++) // 模拟乘法竖式 
			z.num[i + j] += x.num[i] * y.num[j]; 
	for(int i = 0; i < z.len; i++) { // 进位处理 
		z.num[i + 1] += z.num[i] / 10; 
		z.num[i] %= 10;	
	}
	while(z.len > 1 && !z.num[z.len - 1]) --z.len;
	return ;
}

int main() {
	// 读取并倒序存储大整数A 
	scanf("%s", str);
	int len = strlen(str);
	A.len = len;
	for(int i = 0; i < len; i++) A.num[len - i  - 1] = str[i] - '0';
	// 读取并倒序存储大整数B
	scanf("%s", str);
	B.len = len = strlen(str);
	for(int i = 0; i < len; i++) B.num[len - i  - 1] = str[i] - '0';
	Multi(A, B, C); // 计算结果 
	print(C); // 输出 
	return 0;
}

高精除低精:

#include <bits/stdc++.h>

#define MAXN 11111 
using namespace std;

char str[MAXN];

struct BigNum {
	int num[MAXN], len;
}A, B, C;

void print(BigNum &x) { //输出大整数x 
	for(int i = x.len - 1; i >= 0; i--) printf("%d", x.num[i]);
	printf("\n");
}

void Div(BigNum &x, int y, BigNum &z) { 
	z.len = x.len; // 初始长度 
	int t = 0;
	for(int i = z.len - 1; i >= 0; i--) {
		t = t * 10 + x.num[i]; // 当前位数字等于上一位余数乘10再加上当前位数字 
		z.num[i] = t / y; // 除法 
		t %= y; // 更新t 
	}
	while(z.len > 1 && !z.num[z.len - 1]) --z.len; //去除前导0 
	return ;
}

int main() {
	// 读取并倒序存储大整数A 
	scanf("%s", str);
	int len = strlen(str);
	A.len = len;
	for(int i = 0; i < len; i++) A.num[len - i  - 1] = str[i] - '0';
	int y;
	scanf("%d", &y);
	Div(A, y, C); // 计算结果 
	print(C); // 输出 
	return 0;
}

高精除高精:

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

int c[300];
char ch1[300],ch2[300],ans[300];

bool cmp(int p,char ch1[],char ch2[])//对前p位的被除数字符串ch1和整个除数字符串ch2比较大小
{
	int l=1;
	while(ch1[l]=='0'&&l<=p-1) l++;//删除被除数的第p位之前已经被减为0的位
	char tch[300];
	int cnt=0;
	for(int i=l;i<=p;i++)
	{
		tch[++cnt]=ch1[i];//把被除数删完之后的部分存储在tch里
	}
	tch[cnt+1]='\0';
	if(strlen(tch+1)>strlen(ch2+1)||(strlen(tch+1)==strlen(ch2+1)&&strcmp(tch+1,ch2+1)>=0)) return true;
	//如果被除数位数比除数位数多,被除数大
	//如果两者位数相等,根据字母序比较两个字符串大小即可
	else return false;
}

void subtraction(int p,char ch1[],char ch2[])
{
	int l=1;
	while(ch1[l]=='0'&&l<=p-1) l++;//删除被除数的第p位之前已经被减为0的位
	char tch[300];
	int cnt=-1;
	for(int i=l;i<=p;i++)
	{
		tch[++cnt]=ch1[i];//把被除数删完之后的部分存储在tch里
	}
	int ta[300],tb[300];
	memset(ta,0,sizeof(ta));
	memset(tb,0,sizeof(tb));
	int len2=strlen(ch2+1);
	for(int i=1;i<=cnt+1;i++) ta[i]=tch[cnt+1-i]-'0';//把被除数要相减的部分转化为整数数组
	for(int i=1;i<=len2;i++) tb[i]=ch2[len2+1-i]-'0';//把除数转化为整数数组
	int tc[300];
	memset(tc,0,sizeof(tc));
	for(int i=1;i<=cnt+1;i++)//高精度减法模板
	{
		if(ta[i]-tb[i]<0)
		{
			ta[i+1]--;
			ta[i]+=10;
		}
		tc[i]=ta[i]-tb[i];
	}
	for(int i=1;i<=cnt+1;i++)
	{
		ch1[l-1+i]=tc[cnt+2-i]+'0';//将相减的结果又转化成字符串,并更新被除数
	}
}

void add_ans(int p)
{
	ans[p]++;
}

int main()
{
	cin>>ch1+1>>ch2+1;//不用转化为整数数组,每次直接对字符串进行操作
	int len1=strlen(ch1+1);
	int len2=strlen(ch2+1);
	for(int i=len2;i<=len1;i++)//从可能产生答案的最高位len2减到最后一位len1
	{
		while(cmp(i,ch1,ch2)==true)//每位减到不能再减为止,因此这儿需要做个比较
		{
			subtraction(i,ch1,ch2);//用减法模拟每次相除
			add_ans(i);//答案数组的i位上+1
		}
	}
	int l1=1,l2=1;
	while(ans[l1]==0&&l1<=len1-1) l1++;//删除存储商的数组中的多余的前导0
	for(int i=l1;i<=len1;i++) printf("%d",ans[i]);//ans即为存储商的数组
	cout<<endl;
	while(ch1[l2]=='0'&&l2<=len1-1) l2++;//删除余数中多余的前导0
	for(int i=l2;i<=len1;i++) printf("%c",ch1[i]);//ch1(被除数数组)剩余的即为相除余数
	return 0;
}
//出处 sssSSSay
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
 
#define tail head+len2-1//与head联动的tail 记录除数的尾部指针 
#define Init len1=strlen(s1+1),len2=strlen(s2+1);//初始化 
 
const int Maxn=10001;
 
int len1,len2,cur=1;
char s1[Maxn],s2[Maxn];
int a[Maxn],b[Maxn],c[Maxn],ans[Maxn];
 
bool compare(int head)
{
	cur=1;while(a[cur]==0)cur++;//去除a前面的0 便于计算 
	if(tail-cur+1 > len2)return 1;//tail-cur+1即是当前串的长度 
	if(tail-cur+1 < len2)return 0;
	string str1="",str2="";//比大小 
	for(int i=cur;i<=tail;i++){
		str1 += a[i]+48;
		str2 += b[i-head+1]+48;
	}
	if(str1>=str2)return 1;//使用重载过的String类比较 
	else return 0;//如果大于等于就减 小于则不能减 
}
 
int sub(int head)
{
	for(int i=tail;i>=tail-len2+1;i--){//从后往前减 
		a[i]=a[i]-b[i-head+1];//减法 
		if(a[i]<0){//如果不够减借一位 
			a[i]+=10;
			a[i-1]--;
		}
	}
	ans[tail]++;//统计答案 
}
 
int main()
{
	scanf("%s%s",s1+1,s2+1);Init//读入并处理出长度 
	for(int i=1;i<=len1;i++)a[i] = s1[i]-'0';//读入 
	for(int i=1;i<=len2;i++)b[i] = s2[i]-'0';//读入 
	for(int head=1;tail<=len1;head++){//查看该数放在哪一个位置 
		if( !compare(head) )continue;//如果a小于b 则继续下一层 即把b数往后挪一位 
		else while( compare(head) ) sub(head);//只要能减就一直减 直到a小于b 同时在tail处统计答案 
	}
	cur=1;while( ans[cur]==0 && cur!=len1 )cur++;//去除前面的0 
	for(int i=cur;i<=len1;i++)printf("%d",ans[i]);//输出 
}

“基础算法”专栏(目录)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值