FFT高精度乘法

裸FFT走一波~~~

#include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const double PI=acos(-1.0);
char s1[100005];
char s2[100005];
int ans[200005];
struct Complex
{
	double real,ima;
	Complex(double r=0.0,double i=0.0): real(r),ima(i){}
	Complex operator + (Complex &b)const
	{
		return Complex(real+b.real,ima+b.ima);
	}
	Complex operator - (Complex &b)const
	{
		return Complex(real-b.real,ima-b.ima);
	}
	Complex operator * (Complex &b)const
	{
		return Complex(real*b.real-ima*b.ima,real*b.ima+ima*b.real);
	}
};
Complex a[200005];
Complex b[200005];
Complex c[200005];
void rader(Complex* a,int len)
{
	int j=len>>1;
	for(int i=1;i<len-1;i++)
	{
		if(i<j)swap(a[i],a[j]);
		int k=len>>1;
		while(j>=k)
		{
			j-=k;
			k>>=1;
		}
		if(j<k)j+=k;
	}
}
void fft(Complex* a,int len,int on)
{
	rader(a,len);
	for(int ll=2;ll<=len;ll*=2)
	{
		double ang=on*2*PI/ll;
		Complex wn(cos(ang),sin(ang));
		for(int i=0;i<len;i+=ll)
		{
			Complex w(1.0,0.0);
			for(int j=i;j<i+ll/2;j++)
			{
				Complex u=a[j];
				Complex t=w*a[j+ll/2];
				a[j]=u+t;
				a[j+ll/2]=u-t;
				w=w*wn;
			}
		}
	}
	if(on==-1)
	{
		for(int i=0;i<len;i++)
		a[i].real/=len;
	}
}
int main()
{
	scanf("%s%s",s1,s2);
	int lena=strlen(s1);
	int lenb=strlen(s2);
	int len=1;
	while(len<2*lena||len<2*lenb)len*=2;
	int o=0;
	for(o=0;o<lena;o++)
	{
	a[o].real=s1[lena-o-1]-'0';
	a[o].ima=0.0;	
	}
	while(o<len)
	{
	a[o].real=0;	
	a[o].ima=0;	
	o++;
	}
	for(o=0;o<lenb;o++)
	{
	b[o].real=s2[lenb-o-1]-'0';
	b[o].ima=0.0;	
	}
	while(o<len)
	{
	b[o].real=0;	
	b[o].ima=0;
	o++;
	}
	fft(a,len,1);
	fft(b,len,1);
	for(int i=0;i<len;i++)
	c[i]=a[i]*b[i];
	fft(c,len,-1);
	for(int i=0;i<len;i++)
	ans[i]=int(c[i].real+0.5);
	for(int i=0;i<len;i++)
	{
		ans[i+1]+=ans[i]/10;
		ans[i]%=10;
	}
	int high;
	for(int i=len-1;i>=0;i--)
	{
		if(ans[i])
		{
			high=i;
			break;
		}
	}
	for(int i=high;i>=0;i--)
	printf("%d",ans[i]);
	return 0;
}

### 高精度乘法算法概述 高精度乘法是指用于计算超出常规整数表示范围的大数值之间的乘积的一类算法。这类算法不仅解决了传统计算机硬件对于大数运算能力有限的问题,同时也提高了计算效率。 #### 基础方法——长乘法/列乘法 一种基础且直观的方式是模拟人们日常使用的纸笔乘法规则,即所谓的“长乘法”或“列乘法”。这种方法基于手工乘法的过程,在程序设计中通过循环结构来完成多位数间的逐位相乘操作,并妥善处理每次相乘产生的进位情况[^1]。 ```python def multiply_long_form(num1, num2): result = [0] * (len(num1) + len(num2)) for i in reversed(range(len(num1))): for j in reversed(range(len(num2))): mul = int(num1[i]) * int(num2[j]) p1, p2 = i + j, i + j + 1 sum_ = mul + result[p2] result[p1] += sum_ // 10 result[p2] = sum_ % 10 while len(result) > 1 and not result[0]: del result[0] return ''.join(map(str, result)) or '0' ``` 此代码片段展示了如何利用Python实现两个字符串形式的大数之间按位相乘并考虑进位逻辑的函数`multiply_long_form()`。 #### 进阶优化方案 随着研究深入和技术发展,出现了多种更高效的高精度乘法策略: - **分治乘法**:采用递归方式减少所需执行的基本乘法次数,典型代表为Karatsuba算法以及其扩展版本Toom-Cook算法; - **快速傅立叶变换(FFT)** 或者改进版 快速数论变换(FNTT),能够显著降低多项式卷积的时间复杂度至 O(n log n),适用于非常庞大的数字相乘场景; - **中国剩余定理(CRT)** 方法则是借助于模运算特性来进行间接求解,特别适合特定条件下加速计算过程; 上述提到的不同类型的高级技术均能在不同程度上提升性能表现,但具体应用时需综合考量实际需求与资源消耗等因素作出合理选择[^2]。 #### Java中的实践案例 针对Java编程环境下的大数相乘问题,有一种常见的解决方案就是采取逐位相乘再处理进位的办法。这种方式下,会先将参与运算的数据逆序存储在一个数组之中,之后按照位置关系依次配对相乘得到临时结果集,最后调整这些中间产物的位置并通过累加以获得最终答案[^3]。 ```java public class BigIntegerMultiplication { public static String bigIntegerMultiply(String number1, String number2){ if(number1.equals("0") || number2.equals("0")) return "0"; int[] pos = new int[number1.length() + number2.length()]; for(int i=number1.length()-1; i>=0 ;i--){ for(int j=number2.length()-1;j>=0;j--){ int multi = (number1.charAt(i)-'0')*(number2.charAt(j)-'0'); int p1=i+j; int p2=p1+1; int sum = multi + pos[p2]; pos[p1]+=sum / 10; pos[p2]=sum%10; } } StringBuilder sb=new StringBuilder(); boolean flag=false; for(int val :pos){ if(val!=0||flag==true){ sb.append(val); flag=true; } } return sb.toString().equals("")?"0":sb.toString(); } } ``` 这段Java代码实现了类似的逐位相乘机制,其中包含了必要的边界条件判断和零值特判部分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值