高精度算法

介绍一下很可怕但是用处很大的高精度算法叭
两天才学会的可怕算法
基本思路就是用字符串来输入大数
然后把每一位转换成数字进行运算
这样的话两个大数每一位之间的运算就不会爆long long

高精度加法

分析:
高精度加法
将两个大数用字符串输入,前补0弄成长度相同的两个字符串,然后每一位对应相加,定义一个x来记录进位,上一位的和大于9,就用x记录下来进位,加到下一位上即可

洛谷P1601 A+B Problem

/**
高精度加法
**/

//以字符串输出
string s1,s2;
string add(string s1,string s2)
{
    string s;
    int len1 = s1.length();
    int len2 = s2.length();
    //前面补0,弄成长度相同
    if(len1 < len2)
    {
        for(int i=1;i<=len2-len1;i++)
           s1 = "0"+s1;
    }
    else
    {
        for(int i=1;i<=len1-len2;i++)
           s2 = "0"+s2;
    }
    len1 = s1.length();
    int x = 0;//进位 
    int temp;//余数 
    for(int i=len1-1;i>=0;i--)
    {
        temp = s1[i]-'0' + s2[i]-'0' + x;//相加并且加上上一位的进位
        x = temp/10;//计算这一位的进位
        temp %= 10;//保留余数
        s = char(temp+'0')+s;//加进字符串中
    }
    if(x != 0)  s = char(x+'0')+s;//加上最后一位的进位
    return s;
}

int main()
{
	cin >> s1 >> s2;
	cout << add(s1,s2) << endl;
	return 0;
}

//以数组输出
string s1,s2;
int a[maxn],b[maxn],c[maxn];
int alen,blen,len;
int main()
{
	cin >> s1 >> s2;
	memset(c,0,sizeof(c));
    alen = s1.size();
    blen = s2.size();
    for(int i=1;i<=alen;i++)	a[i] = s1[alen-i]-'0';
    for(int i=1;i<=blen;i++)	b[i] = s2[blen-i]-'0';
    int x = 0;//进位 
    if(alen < blen)	swap(alen,blen);
    for(int i=1;i<=alen+1;i++)
    {
    	c[i] = a[i]+b[i]+x;
    	x = c[i]/10;
    	c[i] %= 10;
	}
	len = alen+1;
	while(c[len] == 0 && len > 1)	len--;
	for(int i=len;i>=1;i--)
		printf("%d",c[i]);
	printf("\n");
	return 0;
}

高精度减法

分析:
和之前高精度加法的基本思想相同,只是需要注意,减法要大数减小数,所以要提前比较两个的数大小。每一位对应相减,不够减的话,就借位,即这一位+10,下一位-1,之后再进行减法运算,还要注意0和负数的情况

洛谷P2142 高精度减法

/**
高精度减法
**/
const int maxn = 5e3 + 7;
int a[maxn],b[maxn],c[maxn];
string s,ss;
bool f = 0;//记录结果为正还是为负 
bool compare(int alen,int blen)
//比较一下两个串的大小,只能大数减小数 
{
	if(alen < blen) return true;
	if(alen == blen) return s < ss;
	return false;
}
int main()
{
	cin >> s >> ss;
	int alen = s.size();
	int blen = ss.size();
	if(compare(alen,blen))
	{
		swap(s,ss);
		f = 1;
	}
	alen = s.size();
	blen = ss.size();
	for(int i=1;i<=alen;i++)	a[i] = s[alen-i]-'0';
	for(int i=1;i<=blen;i++)	b[i] = ss[blen-i]-'0';
	//转换成数字存入数组中 
	for(int i=1;i<=alen;i++)
	{
		if(a[i] < b[i])//这一位数字不够减
	 	{
	 		a[i+1]--;//借位,后一位-1,这一位+10 
	 		a[i] += 10;
		 }
		c[i] = a[i]-b[i];//相减 
	}
	int len = alen;
	while(len >= 1 && c[len] == 0) len--;//去掉前导零 
	if(len < 1) printf("0");
	//如果最后长度小于1,说明结果为0,直接输出0
	if(f)	printf("-");
	//如果进行交换,说明被减数小于减数,输出负号 
	for(int i=len;i>=1;i--)
		printf("%d",c[i]);
	printf("\n");
	return 0;   
}

高精度乘法

分析:
将两个大数用字符串表示,输入字符串,将每个字符按逆序转化成数字存放到数组中,然后按照竖式计算的方法,错位相加得到数组c的每一项,然后进行进位运算,最后逆序输出

洛谷P1303 A*B Problem

/**
高精度乘法
**/
char a1[10001],b1[10001];
int a[10001],b[10001],c[10001];
int len,alen,blen;
int main ()
{
    cin >> a1 >> b1;
    int alen = strlen(a1);
    int blen = strlen(b1);
    for(int i=1;i<=alen;i++)	a[i] = a1[alen-i]-'0';
    for(int i=1;i<=blen;i++)	b[i] = b1[blen-i]-'0';
    for(int i=1;i<=blen;i++)
    	for(int j=1;j<=alen;j++)
    		c[i+j-1] += a[j]*b[i];
    //c数组存储好了没有进位之前的 
    for(int i=1;i<alen+blen;i++)
    {
    	if(c[i] > 9)//大于9就需要进位 
    	{
    		c[i+1] += c[i]/10;//给下一位加上进位的数 
    		c[i] %= 10;//这一位保留余数 
		}
	}
	len = alen+blen;
	while(c[len] == 0 && len > 1)
		len--;//去掉前导零 
	for(int i=len;i>=1;i--)
		printf("%d",c[i]);
	printf("\n");
	return 0;
} 

高精度阶乘

分析:
同样的,用一个数组来记录每次相乘后没有进位的乘积,定义一个x来表示每次进位的数字,定义一个p来记录每次相乘得出的数字位数,降低复杂度
因为这个地方我直接用maxn结果超时了
于是就用了一个p来记录数字位数

求N!的值(ni)

题目描述
用递归算法,求N!的精确值(N以一般整数输入)。
输入
10
输出
10!=3628800
样例输入 Copy
10
样例输出 Copy
10!=3628800

/**
高精度阶乘
**/
int c[maxn];
int main()
{
    int n,p;	cin >> n;
    memset(c,0,sizeof(c));
    c[0] = 1;
	p = 1;//用来记录数字位数 
    for(int i=2; i<=n; i++)
	{
        int x = 0;//表示进位
        for(int j=0; j<p; j++)
		{
            c[j] = c[j]*i+x;//这一位+进位
            x = c[j]/10;//判断并存储本次的进位情况 
            c[j] %= 10;//保留进位后的余数 
        }
        while(x > 0)
        {
        	c[p] = x % 10;
        	x /= 10;
        	p++;
		}
    }
    int j;
    for(j=maxn-1;j>=0;j--)	
		if(c[j]) break;//去掉前导零 
    printf("%d!=",n);
	for(int i=j;i>=0;i--)
        printf("%d",c[i]);
    printf("\n");
    return 0;
}

洛谷P1009 阶乘之和

/**
这个题相对于其他高精度题目来说相对简单一点
因为n给出范围n <= 50
所以输入时不需要用字符串进行切换
用数组记录每一位上的数字即可 
**/
int a[2000],b[2000],c[2000];
int sum[2000];
void pplus(int *a,int *c)
{
    int x = 0;
    for(int i=1;i<=1000;i++)
    {
        c[i] += a[i]+x;
        x = c[i]/10;
        c[i] %= 10;
    }
}

void cheng(int *a,int c)
{
    int x = 0;
    for(int i=1;i<=1000;i++)
    {
        a[i] = a[i]*c+x;
        x = a[i]/10;
        a[i] %= 10;
    }
}

int main()
{
    int n;	cin >> n;
    a[1] = 1;
    for(int i=1;i<=n;i++)
    {
        cheng(a,i);//先求i的阶乘放进数组a 
        pplus(a,c);//求一次阶乘加和一次,把每一位放进数组c 
    }
    bool flag = 0;
    for(int i=1000;i>=1;i--)
    {
        if(c[i] != 0) flag=1;
        if(flag) cout << c[i];
    }
    return 0;
}

高精度除法

高精除低精分析:
按位相除保留余数用到下一位的除法上即可

char str[100];
int a[100],b,c[100];
int alen,len;
int main()
{
    memset(a,0,sizeof(a));
    memset(c,0,sizeof(c));
    cin >> str;
    cin >> b;
    int x = 0;
    alen = strlen(str);
    for(int i=0; i<alen; i++)	a[i+1] = str[i]-'0';
    for(int i=1; i<=alen; i++)//按位相除
    {
        c[i] = (x*10+a[i])/b;
        x = (x*10+a[i])%b;
    }
    len = 1;
    while(c[len] == 0 && len < alen)	len++;
    for(int i=len; i<=alen; i++)
		printf("%d",c[i]);
	printf("\n");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你数过天上的星星吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值