好多函数经常用到,于是写好模板以后直接调用~~~
此处贡献本渣的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>