【CodeVS 3123】高精度练习之超大整数乘法

第一次写法法塔,,,感到威力无穷啊

看了一上午算导就当我看懂了?PS:要是机房里能有个清净的看书环境就好了

FFT主要是用了巧妙的复数单位根,复数单位根在复平面上的对称性使得快速傅立叶变换的时间复杂度空降为O(nlogn)←个人的愚蠢理解请随意吐槽

具体的我就不说了,算导上都说得很清楚,说得好像有人会听我说什么似的

模板在这里↓

CodeVS 3123:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1E6 + 3;
const double Pi = acos(- 1.0);
struct cp {
	double r, i;
	cp(double _r = 0.0, double _i = 0.0) : r(_r), i(_i) {}
	cp operator + (const cp &x) const {return cp(r + x.r, i + x.i);}
	cp operator - (const cp &x) const {return cp(r - x.r, i - x.i);}
	cp operator * (const cp &x) const {return cp(r * x.r - i * x.i, r * x.i + i * x.r);}
};
char s[N];
int rev[N];
cp A[N];
void DFT(cp *a, int n, int flag) {
	for(int i = 0; i < n; ++i) A[rev[i]] = a[i];
	for(int i = 0; i < n; ++i) a[i] = A[i];
	for(int m = 2, mid; m <= n; m <<= 1) {
		cp wn(cos(2.0 * Pi / m * flag), sin(2.0 * Pi / m * flag));
		mid = m >> 1;
		for(int i = 0; i < n; i += m) {
			cp w(1.0);
			for(int j = 0; j < mid; ++j) {
				cp u = a[i + j + mid] * w, t = a[i + j];
				a[i + j] = t + u;
				a[i + j + mid] = t - u;
				w = w * wn;
			}
		}
	}
	if (flag == -1)
		for(int i = 0; i < n; ++i)
			a[i].r /= n;
}

void in(cp *a, int &n) {
	scanf("%s", s);
	n = strlen(s);
	for(int i = 0; i < n; ++i)
		a[i].r = s[n - i - 1] - ‘0‘;
}
void init(int &n) {
	int k = 1, L = 0;
	for(; k < n; k <<= 1, ++L);
	n = k;
	for(int i = 0; i < n; ++i) {
		int t = i, ret = 0;
		for(int j = 0; j < L; ++j)
			ret <<= 1, ret |= (t & 1), t >>= 1;
		rev[i] = ret;
	}
}
cp a[N], b[N];
int len = -1, n, ans[N];
void FFT() {
	DFT(a, len, 1); DFT(b, len, 1);
	for(int i = 0; i < len; ++i)
		a[i] = a[i] * b[i];
	DFT(a, len, -1);
}
int main() {
	in(a, n); len += n;
	in(b, n); len += n;
	init(len);
	FFT();
	for(int i = 0; i < len; ++i)
		ans[i] = (int) (a[i].r + 0.5);
	for(int i = 0; i < len; ++i)
		ans[i + 1] += ans[i] / 10, ans[i] %= 10;
	for(++len; ans[len] == 0 && len > 0; --len);
	for(int i = len; i >= 0; --i)
		printf("%d", ans[i]);
	puts("");
	return 0;
}

BZOJ 2197顺便水一水~:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1E6 + 3;
const double Pi = acos(- 1.0);
struct cp {
	double r, i;
	cp(double _r = 0.0, double _i = 0.0) : r(_r), i(_i) {}
	cp operator + (const cp &x) const {return cp(r + x.r, i + x.i);}
	cp operator - (const cp &x) const {return cp(r - x.r, i - x.i);}
	cp operator * (const cp &x) const {return cp(r * x.r - i * x.i, r * x.i + i * x.r);}
};
char s[N];
int rev[N];
cp A[N];
void DFT(cp *a, int n, int flag) {
	for(int i = 0; i < n; ++i) A[rev[i]] = a[i];
	for(int i = 0; i < n; ++i) a[i] = A[i];
	for(int m = 2, mid; m <= n; m <<= 1) {
		cp wn(cos(2.0 * Pi / m * flag), sin(2.0 * Pi / m * flag));
		mid = m >> 1;
		for(int i = 0; i < n; i += m) {
			cp w(1.0);
			for(int j = 0; j < mid; ++j) {
				cp u = a[i + j + mid] * w, t = a[i + j];
				a[i + j] = t + u;
				a[i + j + mid] = t - u;
				w = w * wn;
			}
		}
	}
	if (flag == -1)
		for(int i = 0; i < n; ++i)
			a[i].r /= n;
}

void in(cp *a, int &n) {
	scanf("%s", s);
	n = strlen(s);
	for(int i = 0; i < n; ++i)
		a[i].r = s[n - i - 1] - ‘0‘;
}
void init(int &n) {
	int k = 1, L = 0;
	for(; k < n; k <<= 1, ++L);
	n = k;
	for(int i = 0; i < n; ++i) {
		int t = i, ret = 0;
		for(int j = 0; j < L; ++j)
			ret <<= 1, ret |= (t & 1), t >>= 1;
		rev[i] = ret;
	}
}
cp a[N], b[N];
int len = -1, n, ans[N];
void FFT() {
	DFT(a, len, 1); DFT(b, len, 1);
	for(int i = 0; i < len; ++i)
		a[i] = a[i] * b[i];
	DFT(a, len, -1);
}
int main() {
	scanf("%d\n", &len); len = (len << 1) - 1;
	in(a, n);
	in(b, n);
	init(len);
	FFT();
	for(int i = 0; i < len; ++i)
		ans[i] = (int) (a[i].r + 0.5);
	for(int i = 0; i < len; ++i)
		ans[i + 1] += ans[i] / 10, ans[i] %= 10;
	for(++len; ans[len] == 0 && len > 0; --len);
	for(int i = len; i >= 0; --i)
		printf("%d", ans[i]);
	puts("");
	return 0;
}

高一下半学期开学前的晚上就在看这个东西,拖到现在才理解,累啊~

时间: 2024-11-05 19:29:49

【CodeVS 3123】高精度练习之超大整数乘法的相关文章

Code[VS] 3123 高精度练习之超大整数乘法

FFT 做 高精度乘法 1 #include <bits/stdc++.h> 2 3 const double pi = acos(-1); 4 5 struct complex 6 { 7 double a, b; 8 9 inline complex( 10 double _a = 0, 11 double _b = 0) 12 { 13 a = _a; 14 b = _b; 15 } 16 17 inline friend complex operator + 18 (const com

【CodeVS 3123】 高精度练习之超大整数乘法

RE了2发   init竟然会开小....... 1 #include <cstdio> 2 #include <algorithm> 3 #include <complex> 4 #include <iostream> 5 #include <cmath> 6 using namespace std; 7 const  double PI= acos(-1); 8 int init[100000*4+10]; 9 #define C compl

codevs 3119 高精度练习之大整数开根 (各种高精+压位)

/* codevs 3119 高精度练习之大整数开根 (各种高精+压位) 二分答案 然后高精判重 打了一个多小时..... 最后还超时了...压位就好了 测试点#1.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms 测试点#2.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms 测试点#3.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms 测试点#4.in 结果:AC 内存使用量: 256kB 时间使用量: 10ms 测试点#5.in 结果:AC 内

POJ 1001 解题报告 高精度大整数乘法模版

题目是POJ1001 Exponentiation  虽然是小数的幂 最终还是转化为大整数的乘法 这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于错误的判断还不够严厉. 对边界情况的讨论其实应该是思维严密的表现,当然这并不能表明我写的一点错误都没有,只是多多分析一下还是很有好处的. #include <iostream> #include <fstream> #include <string> #include &l

C语言(7)--高精度加法、减法、乘法、今天是星期几、四位平方数、候选人选票问题

1.高精度加法.减法.乘法 #include <stdio.h> #include <string.h> #include <malloc.h> void plus(char *a,char *b,char *c);//自定义高精度加法函数 void sub(char *a,char *b,char *c);//自定义高精度减法函数 void multiply(char *a,char *b,char *c);//自定义高精度乘法函数 int main() { char

大整数乘法python3实现

由于python具有无限精度的int类型,所以用python实现大整数乘法是没意义的,但是思想是一样的.利用的规律是:第一个数的第i位和第二个数大第j位相乘,一定累加到结果的第i+j位上,这里是从0位置开始算的.代码如下: import sys def list2str(li): while li[0]==0: del li[0] res='' for i in li: res+=str(i) return res def multi(stra,strb): aa=list(stra) bb=l

分治法解大整数乘法

在某些情况下,需要处理很大的整数,它无法在计算机中精确的表述和处理.若要精确的表示大整数,就必须使用软件的方法来实现大整数的运算.最常用的解决大整数运算的方法是使用一个二重循环,其算法时间复杂度为O(m*n)(其中m,n分别为两个大整数的长度):而选用分治方法则可以将算法时间复杂度降到O(n^(log3))(两个大整数的长度同为n).但分治方法的算法实现较为复杂,针对这个问题,本文借助标准C++实现了分治方法求解大整数乘法的算法. 下面分别介绍两种算法原理,及其实现: 1.使用二重循环控制两个数

JavaScript超大整数加法

什么是「超大整数」? JavaScript 采用 IEEE754标准 中的浮点数算法来表示数字 Number. 我也没花时间去详细了解 IEEE754标准 ,但对于处理超大整数,了解下面的几个知识点就足够了. 首先,JavaScript 实际上可以表示的最大数是: 1.7976931348623157e+308 Number.MAX_VALUE; // 1.7976931348623157e+308 虽然这个数可以正确表示出来,但会存在「精度丢失」的问题. 那什么是「精度丢失」? 我们看看下面的

大整数乘法问题

数组可以实现的算法很多,典型应用就是大整数相乘问题.利用的思想非常巧妙,感觉和链表实现多项式运算有异曲同工,大整数相乘主要避免计算机存储精度不够的时候.按照基本的乘法运算实现即可! 主要注意返回指针类型,和关键点k=i的技巧. /*! * \file 算法之美--大整数乘法问题.cpp * * \author ranjiewen * \date 2016/12/04 15:58 * * */ #include <iostream> using namespace std; #define SI