大数问题

一、大数的加法

我们都知道,两个数相加,就是从低位开始相加,满十进一即可。我们可以看出输入的两个加数是倒序存入数组的(存入789和678那么a[0]=7,a[1]=8,a[2]=9:b[0]=6,b[1]=7,b[2]=8),可以看出我们相加时要到着加(即从a[2]+b[2]开始)会很麻烦.并且如果最高位要进位不会有a[-1]来存,所以我们首先要将他们反过来存如数组,那么就可以从a[0]+b[0]开始
下面是将数组倒过来存的代码

void daoxu(char str[],int x[])
{
    int i,j=strlen(str);
    char s;
    for(i=0;i<j;i++)
    {
        s=str[i];      //输入是字符串
        x[j-i-1]=s-'0';//倒过来存入int型数组
    }
}

那么接下来就是从低位开始加,满十进一

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int maxmax=1000;
const int N=2000000;
int y[N];

void daoxu(char str[],int x[])//将输入的大数倒序存入
{
    int i,j=strlen(str);
    char s;
    for(i=0;i<j;i++)
    {
        s=str[i];             //输入是字符串
        x[j-i-1]=s-'0';       //倒过来存入int型数组
    }
}                            //存入结束
void qiu(int a[],int b[],int mun[])
{
    int i;
    for(i=0;i<maxmax;i++)
    {
        mun[i]=a[i]+b[i];
    }
    for(i=0;i<maxmax+1;i++)
        {
            mun[i+1]+=mun[i]/10;//每一位只能留一位数
            mun[i]=mun[i]%10;   //除了留的那一位其余都进位
        }
}
int main()
{
    char s1[maxmax],s2[maxmax];
    int mun[maxmax*2];
    int x1[maxmax];
    int x2[maxmax];
    memset(mun,0,sizeof(mun));//初始化数组
    memset(x1,0,sizeof(x1));  //初始化数组
    memset(x2,0,sizeof(x2));  //初始化数组
    cin >> s1 >> s2;
    daoxu(s1,x1);             //倒序存入数组
    daoxu(s2,x2);             //倒序存入数组
    qiu(x1,x2,mun);           //求两大数相加
    int j=maxmax*2-1,i;
    while(mun[j]==0)          //从最高位开始判断找出第一个非零位
        j--;
    for(i=j;i>=0;i--)         //从高位倒着输出
    {
        printf("%d",mun[i]);
    }
    return 0;
}

二、大数的阶乘

首先看到阶乘大家都会做(一个for循环就可以),那么当这个阶乘结果非常大呢???超过了long long int了呢???
我们知道,乘法就是将被乘数的每一位与乘数相乘,满十进一,那我们不妨用这种思想来写。


#include <iostream>
using namespace std;
int main()
{
    int n,m;
    cin >> m;                    //输入m 代表m组测试数据
    while(m--)
    {
        cin >> n;
        int a[100001];
        int i,j;
        int count=1,next=0,mut;  //mut乘积 next进位 count位数
        a[0]=1;                   
        for (i=2; i<=n; i++)
        {
            for (j=1; j<=count; j++)
            {
                mut=a[j-1]*i+next; //每位乘积等于该位当前乘积加进位数
                a[j-1] = mut%10;   //当前位只能保留一位数
                next = mut/10;     //下一位应加的进位数
            }
            while (next)//next>0  //所剩的应进位数不为0说明总位数不足
            {
                count++;  //总位数加一 直至应进位数为零
                a[count-1] = next%10;//同上“当前位只能保留一位数”
                next = next/10;//同上  “下一位应加的进位数”
            }
        }
        for (i=count-1; i>=0; i--)
            cout << a[i]; //从高位到低位输出
        cout << endl; 
    }
    return 0;
}

那么为了省时我们也可以不把被乘数分成一位一位的,代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int main()
{
    int n,i,j;
    cin >> n;
    int y[200000];
    memset(y,0,sizeof(y));
    int count=0,next=0,num; //mut乘积 next进位 count位数
    y[0]=1;
    for(i=2;i<=n;i++)       //与一位一位乘一样
    {
        for(j=0;j<=count;j++)
        {
            num=y[j]*i+next;
            y[j]=num%10000;
            next=num/10000;
        }
        while(next)
        {
            y[++count]=next%10000;
            next=next/10000;
        }
    }                       //结束
    printf("%d",y[count]);  //输出最高几位
    for(i=count-1;i>=0;i--) //因为除最高位y[]都是四位的
        printf("%04d",y[i]);//不足四位补0
    return 0;
}

大数乘法

看完大数加法和大数阶乘,那么两个大数的乘法就不难理解了。就是先把乘数和被乘数从低位开始拆成一位一位的,并让乘数的每一位乘以被乘数的每一位,错位相加即可

下面我们来展示一道例题的代码
问题 F: 简单A*B

时间限制: 1 Sec 内存限制: 128 MB

题目描述

这是一个非常简单的题,计算A*B的值。

输入

第一行:数A

第二行:数B

数A,B是不超过1000位的正整数。

输出

A*B的值,答案独占一行。

样例输入

123456
234567

样例输出

28958703552

代码展示
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int maxmax=1000;
const int N=2000000;
int y[N];

void daoxu(char str[],int x[])//将输入的大数倒序存入
{
    int i,j=strlen(str);
    char s;
    for(i=0;i<j;i++)
    {
        s=str[i];             //输入是字符串
        x[j-i-1]=s-'0';       //倒过来存入int型数组
    }
}                            //存入结束
void qiu(int a[],int b[],int mun[])
{
    int i,j;
    for(i=0;i<maxmax;i++)
    {
        for(j=0;j<maxmax;j++)
        {
            mun[i+j]+=a[i]*b[j];
            //将乘数每一位乘以被乘数每一位
            //num[i+j]是因为要错一位相加
        }
    }
    for(i=0;i<maxmax*2-1;i++)
        {
            mun[i+1]+=mun[i]/10;//每一位只能留一位数
            mun[i]=mun[i]%10;   //除了留的那一位其余都进位
        }
}
int main()
{
    char s1[maxmax],s2[maxmax];
    int mun[maxmax*2];
    int x1[maxmax];
    int x2[maxmax];
    memset(mun,0,sizeof(mun));//初始化数组
    memset(x1,0,sizeof(x1));  //初始化数组
    memset(x2,0,sizeof(x2));  //初始化数组
    cin >> s1 >> s2;
    daoxu(s1,x1);             //倒序存入数组
    daoxu(s2,x2);             //倒序存入数组
    qiu(x1,x2,mun);           //求两大数相乘
    int j=maxmax*2-1,i;
    while(mun[j]==0)          //从最高位开始判断找出第一个非零位
        j--;
    for(i=j;i>=0;i--)         //从高位倒着输出
    {
        printf("%d",mun[i]);
    }
    return 0;
}


阅读更多
上一篇01背包问题
想对作者说点什么? 我来说一句

大数算法PDF

2014年08月15日 87KB 下载

大数运算方法

2013年01月05日 4.83MB 下载

ACM大数常见处理模板

2009年09月24日 4KB 下载

无符号大数计算

2015年07月16日 4KB 下载

大数计算器

2014年12月18日 156KB 下载

简单大数运算

2012年10月03日 652B 下载

大数与数论(acm算法很好的)

2011年05月13日 346KB 下载

C解决大数问题

2013年04月21日 94KB 下载

没有更多推荐了,返回首页

关闭
关闭