大数加法和大数乘法模板函数

好多函数经常用到,于是写好模板以后直接调用~~~

此处贡献本渣的C++版的大数加法和大数乘法模板,

在没有Java的恶劣环境下,渣渣用此模板度过了菜鸟时光(如今依旧菜鸟。。。。)


大数加法华丽版(紫书作者刘大大支持负数版)

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
using namespace std;
struct BigInteger
{
    static const int BASE = 100000000;
    static const int WIDTH = 8;
    vector<int> s;

    BigInteger (long long num = 0)
    {
        *this = num;    // 构造函数
    }
    BigInteger operator = (long long num)   // 赋值运算符
    {
        s.clear();
        do
        {
            s.push_back (num % BASE);
            num /= BASE;
        }
        while (num > 0);
        return *this;
    }
    BigInteger operator = (const string& str)   // 赋值运算符
    {
        s.clear();
        int x, len = (str.length() - 1) / WIDTH + 1;
        for (int i = 0; i < len; i++)
        {
            int end = str.length() - i * WIDTH;
            int start = max (0, end - WIDTH);
            sscanf (str.substr (start, end - start).c_str(), "%d", &x);
            s.push_back (x);
        }
        return *this;
    }
    BigInteger operator + (const BigInteger& b) const
    {
        BigInteger c;
        c.s.clear();
        for (int i = 0, g = 0; ; i++)
        {
            if (g == 0 && i >= s.size() && i >= b.s.size() ) break;
            int x = g;
            if (i < s.size() ) x += s[i];
            if (i < b.s.size() ) x += b.s[i];
            c.s.push_back (x % BASE);
            g = x / BASE;
        }
        return c;
    }
};
ostream& operator << (ostream &out, const BigInteger& x)
{
    out << x.s.back();
    for (int i = x.s.size() - 2; i >= 0; i--)
    {
        char buf[20];
        sprintf (buf, "%08d", x.s[i]);
        for (int j = 0; j < strlen (buf); j++) out << buf[j];
    }
    return out;
}
istream& operator >> (istream &in, BigInteger& x)
{
    string s;
    if (! (in >> s) ) return in;
    x = s;
    return in;
}
#include<set>
#include<map>
set<BigInteger> s;
map<BigInteger, int> m;
int main()
{
    BigInteger y;
    BigInteger x = y;
    BigInteger z = 123;

    BigInteger a, b;
    while(cin >> a >> b) cout << a + b << "\n";
//    cout << BigInteger::BASE << "\n";
    return 0;
}


大数加法(菜鸟版。。。不支持负数。。):

//Must so
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

string Bigadd(string s1,string s2)
{
     string s;
     int l1 =  s1.size(),l2 = s2.length(),mx;
	if (l1 > l2)
	{
		mx = l1;
		string ex(l1 - l2,'0');
		s2 = ex + s2;
	}
	else
	{
		mx = l2;
		string ex(l2 - l1,'0');
		s1 = ex + s1;
	}
	int jingwei = 0,ans;
	for (int i = mx - 1;i >= 0;i--)
	{
		ans = s1[i] + s2[i] - 96 + jingwei;
		jingwei = ans / 10;
		char a = ans % 10 + 48;
		s = a + s;
	}
	char a = jingwei + 48;
	if (a != '0') s = a + s;
	return s;
}
int main()
{
    string a,b;
    cin>>a>>b;
    cout<<Bigadd(a,b)<<endl;
    return 0;
}


PS:关于大数加法,我记得见过一种非常牛逼的处理,当时大致估摸最后的结果不超过10的32次方,
于是某位大神用2个long long ,一个记录尾,一个记录头,只模拟了大数加法的一部分

这种方法对于某些题目稍稍溢出long log的情况很好用(毕竟代码长度和时间复杂度都会比完整的大数加法优化很多)

相关题目和代码最后贴上供参考~~~


大数乘法:

//Must so
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<ctype.h>
#include<queue>
#include<vector>
#include<set>
#include<cstdio>
#include<cmath>
#define mem(a,x) memset(a,x,sizeof(a))
#define ex(x) ((x)*(x))
#define inf 1<<29
#define NN 1000006
using namespace std;
const double PI = acos(-1.0);
typedef long long LL;
int c[10000];
string bigmul(string a,string b)
{
    int aa = a.size(),bb = b.size(),cc = aa + bb;
    for (int i = 0;i < cc;i++) c[i] = 0;
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());
    for (int i = 0; i < aa; i++)
    {
        for (int j = 0; j < bb; j++)
        {
            c[i+j] += (a[i]-48)*(b[j]-48);
        }
    }
    for (int i = 0; i < cc-1; i++)
    {
        c[i+1] += c[i]/10;
        c[i] = c[i]%10;
    }
    int i = cc-1;
    while (c[i--] == 0);
    string ans;
    for (int j = i+1;j >= 0;j--) ans += (c[j]+48);
    return ans;
}
int main()
{
    string a,b;
    while (cin>>a>>b)
    {
        cout<<bigmul(a,b)<<endl;
    }
    return 0;
}



关于大数加法一个巧妙的方法:

题目链接:点击打开链接

这个题目我是用母函数做的,大牛们则是完全背包做的....我是很久之后才被告知母函数是冷门技巧....

AC代码:

//Must so
//母函数
#include<cstdio>
#include<iostream>
using namespace std;
long long c1[1001],c2[1001];
long long pre1[1001],pre2[1001];//c1,c2是尾数,pre1,pre2是前面的高位部分
int main()
{
    long long mod = 1;
    for (int i = 0;i < 18;i++) mod *= 10;//18位
    int n,k;
    while (~scanf("%d%d",&n,&k))
    {
        for (int i = 0;i <= n;i++)
        {
            c1[i] = 1;
            pre1[i] = 0;
            c2[i] = 0;
            pre2[i] = 0;
        }
        for (int i = 2;i <= k;i++)
        {
            for (int j = 0;j <= n;j++)
            {
                for (int k = 0;k+j <= n;k += i)
                {
                    c2[j+k] += c1[j];
                    pre2[j+k] += pre1[j];
                   // if (pre2[j+k]) printf("---%lld---???\n",pre2[j+k]);
                    pre2[j+k] += c2[j+k]/mod;//进位
                    c2[j+k] %= mod;//取余

                }
            }
            for (int j = 0;j <= n;j++)
            {
                c1[j] = c2[j];
                pre1[j] = pre2[j];
                c2[j] = 0;
                pre2[j] = 0;
            }
        }
       // printf("-----%lld-----\n",pre1[n]);
        if (pre1[n]) printf("%lld",pre1[n]);
        printf("%lld\n",c1[n]);
    }
    return 0;
}


</pre><pre>
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值