HDU_1402_A * B Problem Plus

A * B Problem Plus

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


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

  • 数据量5w
  • 简单乘法运算n^2复杂度显然不可行
  • 现在将整数乘法看成变量x=10的多项式相乘
  • 每一位上的数字为各项系数
  • 用FFT计算卷积,把复杂度降到nlogn
  • 详见代码FFT模板

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
typedef long long           LL ;
typedef unsigned long long ULL ;
const int    maxn = 140000 + 10;
const int    inf  = 0x3f3f3f3f ;
const int    npos = -1         ;
const int    mod  = 1e9 + 7    ;
const int    mxx  = 100 + 5    ;
const double eps  = 1e-6       ;
const double PI   = acos(-1.0) ;

struct Complex{
	double r, i;
	Complex(double x=0.0, double y=0.0){
		reset(x,y);
	}
	void reset(double x, double y){
		r=x;
		i=y;
	}
	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));
	}
};
Complex A[maxn];
void FFT(Complex *a, int n, int op){
	for(int i=0;i<n;i++){
		int j=0;
		for(int k=0;(1<<k)<n;k++){
			j<<=1;
			if(i & (1<<k))
				j|=1;
		}
		A[j]=a[i];
	}
	for(int d=0;(1<<d)<n;d++){
		int m=1<<d;
		int m2=m<<1;
		double p0=PI/m*op;
		Complex unit_p0(cos(p0),sin(p0));
		for(int i=0;i<n;i+=m2){
			Complex unit(1,0);
			for(int j=0;j<m;j++){
				Complex &p1=A[i+j+m], &p2=A[i+j];
				Complex t=unit*p1;
				p1=p2-t;
				p2=p2+t;
				unit=unit*unit_p0;
			}
		}
	}
	if(-1==op)
		for(int i=0;i<n;i++){
			A[i].r/=n;
			A[i].i/=n;
		}
	for(int i=0;i<n;i++)
		a[i]=A[i];
}
Complex c[maxn], d[maxn];
char a[maxn], b[maxn];
int f[maxn], la, lb, n, sa, sb, flag;
int main(){
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	while(~scanf("%s",a)){
		la=strlen(a);
		sa=0;
		while((1<<sa)<la)sa++;
		scanf("%s",b);
		lb=strlen(b);
		sb=0;
		while((1<<sb)<lb)sb++;
		n=1<<max(sa+1,sb+1);
		for(int i=0;i<n;i++){
			if(i<la){
				c[i].reset(a[la-i-1]-'0',0);
			}else{
				c[i].reset(0,0);
			}
			if(i<lb){
				d[i].reset(b[lb-i-1]-'0',0);
			}else{
				d[i].reset(0,0);
			}
		}
		FFT(c,n,1);
		FFT(d,n,1);
		for(int i=0;i<n;i++)
			c[i]=c[i]*d[i];
		
		FFT(c,n,-1);
		for(int i=0;i<n;i++)
			f[i]=(int)(c[i].r+0.5);
		for(int i=0;i<n-1;i++){
			f[i+1]+=f[i]/10;
			f[i]%=10;
		}
		flag=0;
		for(int i=n-1;i>=0;i--){
			if(f[i]){
				printf("%d",f[i]);
				flag=1;
			}else if(flag || 0==i){
				printf("0");
			}
		}
		puts("");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值