A * B Problem Plus

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 9413    Accepted Submission(s): 1468

Problem Description
Calculate A * B.
 
Input
Each line will contain two integers A and B. Process to end of file.

Note: the length of each integer will not exceed 50000.

 
Output
For each case, output A * B in one line.
 
Sample Input
1
2
1000
2
 
Sample Output
2
2000
 
Author
DOOM III
 
Recommend
DOOM III
 

神奇的FFT。

如果是乘法,位数为n和位数为m的相乘,需要n*m次的乘法运算。

FFT在数字信号处理学过,但是第一次用来做这类题目,神奇啊。

乘法其实就是做线性卷积。

用DFT得方法可以求循环卷积,但是当循环卷积长度L≥N+M-1,就可以做线性卷积了。

使用FFT将两个数列转换成傅里叶域,在这的乘积就是时域的卷积。

给几个学习的链接吧:

http://wenku.baidu.com/view/8bfb0bd476a20029bd642d85.html  (这主要看那个FFT的流程图)

http://wlsyzx.yzu.edu.cn/kcwz/szxhcl/kechenneirong/jiaoan/jiaoan3.htm   这有DFT的原理。

整理了个模板,感觉很赞!

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std; const double PI = acos(-1.0);
//复数结构体
struct complex
{
double r,i;
complex(double _r = 0.0,double _i = 0.0)
{
r = _r; i = _i;
}
complex operator +(const complex &b)
{
return complex(r+b.r,i+b.i);
}
complex operator -(const complex &b)
{
return complex(r-b.r,i-b.i);
}
complex operator *(const complex &b)
{
return complex(r*b.r-i*b.i,r*b.i+i*b.r);
}
};
/*
* 进行FFT和IFFT前的反转变换。
* 位置i和 (i二进制反转后位置)互换
* len必须去2的幂
*/
void change(complex y[],int len)
{
int i,j,k;
for(i = , j = len/;i < len-; i++)
{
if(i < j)swap(y[i],y[j]);
//交换互为小标反转的元素,i<j保证交换一次
//i做正常的+1,j左反转类型的+1,始终保持i和j是反转的
k = len/;
while( j >= k)
{
j -= k;
k /= ;
}
if(j < k) j += k;
}
}
/*
* 做FFT
* len必须为2^k形式,
* on==1时是DFT,on==-1时是IDFT
*/
void fft(complex y[],int len,int on)
{
change(y,len);
for(int h = ; h <= len; h <<= )
{
complex wn(cos(-on**PI/h),sin(-on**PI/h));
for(int j = ;j < len;j+=h)
{
complex w(,);
for(int k = j;k < j+h/;k++)
{
complex u = y[k];
complex t = w*y[k+h/];
y[k] = u+t;
y[k+h/] = u-t;
w = w*wn;
}
}
}
if(on == -)
for(int i = ;i < len;i++)
y[i].r /= len;
}
const int MAXN = ;
complex x1[MAXN],x2[MAXN];
char str1[MAXN/],str2[MAXN/];
int sum[MAXN];
int main()
{
while(scanf("%s%s",str1,str2)==)
{
int len1 = strlen(str1);
int len2 = strlen(str2);
int len = ;
while(len < len1* || len < len2*)len<<=;
for(int i = ;i < len1;i++)
x1[i] = complex(str1[len1--i]-'',);
for(int i = len1;i < len;i++)
x1[i] = complex(,);
for(int i = ;i < len2;i++)
x2[i] = complex(str2[len2--i]-'',);
for(int i = len2;i < len;i++)
x2[i] = complex(,);
//求DFT
fft(x1,len,);
fft(x2,len,);
for(int i = ;i < len;i++)
x1[i] = x1[i]*x2[i];
fft(x1,len,-);
for(int i = ;i < len;i++)
sum[i] = (int)(x1[i].r+0.5);
for(int i = ;i < len;i++)
{
sum[i+]+=sum[i]/;
sum[i]%=;
}
len = len1+len2-;
while(sum[len] <= && len > )len--;
for(int i = len;i >= ;i--)
printf("%c",sum[i]+'');
printf("\n");
}
return ;
}

HDU 1402 A * B Problem Plus (FFT求高精度乘法)的更多相关文章

  1. HDU - 1402 A * B Problem Plus (FFT实现高精度乘法)

    题意:计算A*B,A,B均为长度小于50000的整数. 这是FFT在大整数相乘中的一个应用,我本来想用NTT做的,但NTT由于取模很可能取炸,所以base必须设得很小,而且效率也比不上FFT. A和B ...

  2. hdu 1402 A * B Problem Plus FFT

    /* hdu 1402 A * B Problem Plus FFT 这是我的第二道FFT的题 第一题是完全照着别人的代码敲出来的,也不明白是什么意思 这个代码是在前一题的基础上改的 做完这个题,我才 ...

  3. HDU - 1402 A * B Problem Plus FFT裸题

    http://acm.hdu.edu.cn/showproblem.php?pid=1402 题意: 求$a*b$ 但是$a$和$b$的范围可以达到 $1e50000$ 题解: 显然...用字符串模拟 ...

  4. HDU 1402 A * B Problem Plus (FFT模板题)

    FFT模板题,求A*B. 用次FFT模板需要注意的是,N应为2的幂次,不然二进制平摊反转置换会出现死循环. 取出结果值时注意精度,要加上eps才能A. #include <cstdio> ...

  5. SPOJ - VFMUL - Very Fast Multiplication FFT加速高精度乘法

    SPOJ - VFMUL:https://vjudge.net/problem/SPOJ-VFMUL 这是一道FFT求高精度的模板题. 参考:https://www.cnblogs.com/Rabbi ...

  6. P1919 FFT加速高精度乘法

    P1919 FFT加速高精度乘法 传送门:https://www.luogu.org/problemnew/show/P1919 题意: 给出两个n位10进制整数x和y,你需要计算x*y. 题解: 对 ...

  7. HDU 1402 A * B Problem Plus 快速傅里叶变换 FFT 多项式

    http://acm.hdu.edu.cn/showproblem.php?pid=1402 快速傅里叶变换优化的高精度乘法. https://blog.csdn.net/ggn_2015/artic ...

  8. FFT实现高精度乘法

    你应该知道$FFT$是用来处理多项式乘法的吧. 那么高精度乘法和多项式乘法有什么关系呢? 观察这样一个$20$位高精度整数$11111111111111111111$ 我们可以把它处理成这样的形式:$ ...

  9. BZOJ2179: FFT快速傅立叶 FFT实现高精度乘法

    Code: #include <cstdio> #include <algorithm> #include <cmath> #include <cstring ...

随机推荐

  1. 动态规划&字符串:最长公共子串

    还是直接上转移方程: 动规只能解决O(n^2)的最长公共子串问题 使用后缀数组或者SAM可以高效地解决这个问题 所以,对于这个问题,动规的代码就不给出了 直接给出SAM的实现,也为以后学习SAM打下一 ...

  2. 【SPOJ-QTREE3】树链剖分

    http://www.spoj.com/problems/QTREE3/ 时间限制:2s    代码长度限制:50000B     内存限制:1536MB [题目描述] 给出N个点的一棵树(N-1条边 ...

  3. bzoj3127/3697 [Usaco2013 Open]Yin and Yang

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3127 http://www.lydsy.com/JudgeOnline/problem.ph ...

  4. cdp协议通信并发编程基础之进程

    一 . 基于UDP的套接字 udp是无链接的所以先启动哪一段都不会报错 udp服务端 import socket server=socket.socket(socket.AF_INET,socket. ...

  5. celey异步任务

    参考:http://yshblog.com/blog/163 """ 需安装软件: pip install celery sudo apt-get install red ...

  6. [Leetcode Week10]Minimum Time Difference

    Minimum Time Difference 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/minimum-time-difference/desc ...

  7. linux 中解析命令行参数(getopt_long用法)

    linux 中解析命令行参数(getopt_long用法) http://www.educity.cn/linux/518242.html 详细解析命令行的getopt_long()函数 http:/ ...

  8. 利用php设置url转发 - 解决空间不提供子目录绑定功能的问题

    由于很多新手都是使用的虚拟空间都是最便宜的那种,这空间一般不支持子目录绑定.但是很多朋友又想设置几个不同的二级域名访问不同的网站程序.于是大家找到了域名url转发,但是由于国家政策的原因,许多服务商暂 ...

  9. css左右箭头

    .record-left{ content: ""; width: 0; height: 0; float: left; border-top: 10px solid transp ...

  10. src2中的alpha融合ROI

    #include <cv.h> #include <highgui.h> int main(int argc, char** argv) { IplImage *src1,*s ...