A * B Problem Plus

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

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
 
解析   FFT入门题   一个整数可以看成是一个多项式   1234=4*10^0+3*10^1+2*10^2+1*10^3
   数据好像有前导零  要处理一下。。
 
这个是结构体实现的  跑的比较快的代码
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n");
using namespace std;
typedef long long ll;
const ll maxn=3e5+,inf=0x3f3f3f3f;
const ll mod=1e9+;
const double PI = acos(-1.0);
//复数结构体 c++自带复数容器 用万能头的话会重名
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;
}
char num1[maxn], num2[maxn];
complex x1[maxn], x2[maxn];
int ans[maxn];
int main() {
while(scanf("%s%s",num1,num2)!=EOF) {
memset(ans, , sizeof(ans));
int len = , len1 = strlen(num1), len2 = strlen(num2);
while(len<len1+len2+) len <<= ;
for(int i = ; i < len1; i++) x1[len1--i] = complex((double)(num1[i]-''), );
for(int i = len1; i < len; i++) x1[i] = complex(, );
fft(x1, len, );
for(int i = ; i < len2; i++) x2[len2--i] = complex((double)(num2[i]-''), );
for(int i = len2; i < len; i++) x2[i] = complex(, );
fft(x2, len, );
for(int i = ; i < len; i++) x1[i] = x1[i] * x2[i];
fft(x1, len, -);
for(int i = ; i < len; i++) ans[i] = (int)(x1[i].r+0.5);
for(int i = ; i < len; i++) {
ans[i] += ans[i-]/;
ans[i-] %= ;
}
while(len> && !ans[len]) len--;
for(int i = len; i >= ; i--) printf("%c", ans[i]+'');
puts("");
}
return ;
}

这个是complex实现的 慢一点 这个初始化占内存而且费时 因为把根都提前存好了

#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n");
#define debug(a,b) cout<<a<<" "<<b<<" ";
using namespace std;
typedef long long ll;
const ll maxn=2e5+,inf=0x3f3f3f3f;
const ll mod=1e9+;
const double PI = acos(-);
typedef complex <double> cp;
char sa[maxn], sb[maxn];
int n = , lena, lenb, res[maxn];
cp a[maxn], b[maxn], omg[maxn], inv[maxn];
void init(){
for(int i = ; i < n; i++){
a[i]=b[i]=cp(,);
omg[i] = cp(cos( * PI * i / n), sin( * PI * i / n));
inv[i] = conj(omg[i]); //conj共轭复数
}
memset(res,,sizeof(res));
}
void fft(cp *a, cp *omg){
int lim = ;
while(( << lim) < n) lim++;
for(int i = ; i < n; i++){
int t = ;
for(int j = ; j < lim; j++)
if((i >> j) & ) t |= ( << (lim - j - ));
if(i < t) swap(a[i], a[t]); // i < t 的限制使得每对点只被交换一次(否则交换两次相当于没交换)
}
for(int l = ; l <= n; l *= ){
int m = l / ;
for(cp *p = a; p != a + n; p += l)
for(int i = ; i < m; i++){
cp t = omg[n / l * i] * p[i + m];
p[i + m] = p[i] - t;
p[i] += t;
}
}
}
int main(){ while(scanf("%s%s", sa, sb)!=EOF){
n=,lena = strlen(sa), lenb = strlen(sb);
while(n < lena + lenb) n *= ; //n必须是2的次幂'
init();
for(int i = ; i < lena; i++)
a[i].real(sa[lena - - i] - '');
for(int i = ; i < lenb; i++)
b[i].real(sb[lenb - - i] - '');
fft(a, omg);
fft(b, omg);
for(int i = ; i < n; i++)
a[i] *= b[i];
fft(a, inv);
for(int i = ; i < n; i++){
res[i] += floor(a[i].real() / n + 0.5);
res[i + ] += res[i] / ;
res[i] %= ;
}
while(n>&&!res[n])n--; //抛去前导零
for(int i = n; i >= ; i--)
putchar('' + res[i]);
puts("");
}
return ;
}

这是我改编版本一的代码

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n");
using namespace std;
typedef long long ll;
typedef complex<double> complexd;
const ll maxn=3e5+,inf=0x3f3f3f3f;
const ll mod=1e9+;
const double PI = acos(-1.0);
/*
* 进行FFT和IFFT前的反转变换。
* 位置i和 (i二进制反转后位置)互换
* len必须取2的幂
*/
void change(complexd *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(complexd *y,int len,int on)
{
change(y,len);
for(int h = ; h <= len; h <<= )
{
complexd wn(cos(-on**PI/h),sin(-on**PI/h));
for(int j = ; j < len; j+=h)
{
complexd w(,);
for(int k = j; k < j+h/; k++)
{
complexd u = y[k];
complexd 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]=complexd(y[i].real()/len,y[i].imag());
}
char num1[maxn], num2[maxn];
complexd x1[maxn], x2[maxn];
int ans[maxn];
int main()
{
while(scanf("%s%s",num1,num2)!=EOF)
{
memset(ans, , sizeof(ans));
int len = , len1 = strlen(num1), len2 = strlen(num2);
while(len<len1+len2+)
len <<= ;
for(int i = ; i < len1; i++)
x1[len1--i] = complexd((double)(num1[i]-''), );
for(int i = len1; i < len; i++)
x1[i] = complexd(, );
fft(x1, len, );
for(int i = ; i < len2; i++)
x2[len2--i] = complexd((double)(num2[i]-''), );
for(int i = len2; i < len; i++)
x2[i] = complexd(, );
fft(x2, len, );
for(int i = ; i < len; i++)
x1[i] = x1[i] * x2[i];
fft(x1, len, -);
for(int i = ; i < len; i++)
ans[i] = (int)(x1[i].real()+0.5);
for(int i = ; i < len; i++)
{
ans[i] += ans[i-]/;
ans[i-] %= ;
}
while(len> && !ans[len])
len--;
for(int i = len; i >= ; i--)
printf("%c", ans[i]+'');
puts("");
}
return ;
}

NTT  模意义下的FFT

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std; inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<=''&&ch>=''){x=*x+ch-'';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<)putchar('-'),x=-x;if(x>=)print(x/);putchar(x%+'');} const int N=,P=; inline int qpow(int x,int y)
{
int res();
while(y)
{
if(y&) res=1ll*res*x%P;
x=1ll*x*x%P;
y>>=;
}
return res;
} int r[N]; void ntt(int *x,int lim,int opt)
{
register int i,j,k,m,gn,g,tmp;
for(i=;i<lim;++i)
if(r[i]<i)
swap(x[i],x[r[i]]);
for(m=;m<=lim;m<<=)
{
k=m>>;
gn=qpow(,(P-)/m);
for(i=;i<lim;i+=m)
{
g=;
for(j=;j<k;++j,g=1ll*g*gn%P)
{
tmp=1ll*x[i+j+k]*g%P;
x[i+j+k]=(x[i+j]-tmp+P)%P;
x[i+j]=(x[i+j]+tmp)%P;
}
}
}
if(opt==-)
{
reverse(x+,x+lim);
register int inv=qpow(lim,P-);
for(i=;i<lim;++i)
x[i]=1ll*x[i]*inv%P;
}
} int A[N],B[N],C[N]; char a[N],b[N]; int main()
{
register int i,lim(),n;
while(scanf("%s%s",a,b)!=EOF)
{
memset(C,,sizeof(C));
memset(A,,sizeof(A));
memset(B,,sizeof(B));
n=strlen(a);
for(i=;i<n;++i) A[i]=a[n-i-]-'';
while(lim<(n<<)) lim<<=;
n=strlen(b);
for(i=;i<n;++i) B[i]=b[n-i-]-'';
while(lim<(n<<)) lim<<=;
for(i=;i<lim;++i)
r[i]=(i&)*(lim>>)+(r[i>>]>>);
ntt(A,lim,);ntt(B,lim,);
for(i=;i<lim;++i)
C[i]=1ll*A[i]*B[i]%P;
ntt(C,lim,-);
int len();
for(i=;i<lim;++i)
{
if(C[i]>=)
len=i+,
C[i+]+=C[i]/,C[i]%=;
if(C[i]) len=max(len,i);
}
while(C[len]>=)
C[len+]+=C[len]/,C[len]%=,len++;
for(i=len;~i;--i)
putchar(C[i]+'');
puts("");
}
return ;
}

FFT原理学习   https://zhuanlan.zhihu.com/p/40505277?utm_source=qq&utm_medium=social&utm_oi=854653490251829248

        https://www.cnblogs.com/RabbitHu/p/FFT.html

HDU 1402 大数乘法 FFT、NTT的更多相关文章

  1. [hdu1402]大数乘法(FFT模板)

    题意:大数乘法 思路:FFT模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ...

  2. hdu 5666 (大数乘法) Segment

    题目:这里 题意:在线段x+y=q与坐标轴围成的三角形中,求有多少个坐标为整数的点,答案模上p. 很容易就想到最后答案就是((q-1)*(q-2))/2然后模上p就是了,但是这个数字比较大,相乘会爆l ...

  3. HDU 1402 FFT 大数乘法

    $A * B$ FFT模板题,找到了一个看起来很清爽的模板 /** @Date : 2017-09-19 22:12:08 * @FileName: HDU 1402 FFT 大整数乘法.cpp * ...

  4. hdu 1402(FFT乘法 || NTT乘法)

    A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  5. hdu 1402 A * B Problem Plus FFT

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

  6. 【Uoj34】多项式乘法(NTT,FFT)

    [Uoj34]多项式乘法(NTT,FFT) 题面 uoj 题解 首先多项式乘法用\(FFT\)是一个很久很久以前就写过的东西 直接贴一下代码吧.. #include<iostream> # ...

  7. 1028 大数乘法 V2(FFT or py)

    1028 大数乘法 V2 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 给出2个大整数A,B,计算A*B的结果.   Input 第1行:大数A 第2行:大数B ...

  8. ACM学习历程—51NOD1028 大数乘法V2(FFT)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1028 题目大意就是求两个大数的乘法. 但是用普通的大数乘法,这 ...

  9. A * B Problem Plus HDU - 1402 (FFT)

    A * B Problem Plus HDU - 1402 (FFT) Calculate A * B.  InputEach line will contain two integers A and ...

随机推荐

  1. 分类IP地址(A、B、C类)的指派范围、一般不使用的特殊IP地址

    分类IP地址(A.B.C类)的指派范围.一般不使用的特殊IP地址 A类地址:0开头,8位网络号 B类地址:10开头,16位网络号 C类地址:110开头,24位网络号 D类地址:1110开头,多播地址 ...

  2. dos command

    dos command md 创建目录 rd 删除目录 cd\ 返回到根目录 cd.. 返回到上一级目录 cd 进入指定目录 dir 列出当前目录下的文件夹及文件 echo 文件内容>文件名称. ...

  3. Hydraulic Motor Manufacturers - What Is A Cycloidal Hydraulic Motor?

    The     Hydraulic Motor manufacturers    stated that the cycloidal hydraulic motor is fixedly connec ...

  4. grep取缩写|awk两个文件取交集

    #!/bin/sh les species_latinName_abbr.txt|grep -E 'Aptenodytes|Gavia|Phoenicopterus|Chlamydotis|Phaet ...

  5. ajax从入门到深入精通

    前言 ajax全称Asynchronous Javascript and XML.其中Asynchronous代表异步.同步于异步是描述通信模式的概念,同步机制:发送方发生请求后,需要等待接收到接收方 ...

  6. C指针类型转换问题

    先看下面的代码: #include<stdio.h> int main () { int a; char *x; x = (char *) &a; a = 512; x[0] = ...

  7. 牛客网练习赛25 C 再编号

    链接:https://www.nowcoder.com/acm/contest/158/C来源:牛客网 定义对 a 的再编号为 a' ,满足 . 现在有 m 次询问,每次给定 x,t ,表示询问经过 ...

  8. POJ-1190-生日蛋糕(深搜,剪枝)

    生日蛋糕 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 23049 Accepted: 8215 Description 7月1 ...

  9. 【模板】插头dp

    题目描述 题解: 插头$dp$中经典的回路问题. 首先了解一下插头. 一个格子,上下左右四条边对应四个插头.就像这样: 四个插头. 一个完整的哈密顿回路,经过的格子一定用且仅用了两个插头. 所以所有被 ...

  10. redis搭建配置

    1 .去官方下载 2.解压tar 3.进入解压目录 编译 4.将编译好的目录移动到制定位置.做软连接 .配置环境便利 5.创建数据保存目录.创建配置文件 [root@radis ~]# vim /da ...