【FFT】hdu1402 A * B Problem Plus

FFT板子。

将大整数看作多项式,它们的乘积即多项式的乘积在x=10处的取值。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define EPS 1e-8
const double PI = acos(-1.0);
struct Complex{
	double real,image;
	Complex(double _real,double _image){
		real=_real;
		image=_image;
	}
	Complex(){}
};
Complex operator + (const Complex &c1,const Complex &c2){
	return Complex(c1.real+c2.real,c1.image+c2.image);
}
Complex operator - (const Complex &c1,const Complex &c2){
	return Complex(c1.real-c2.real,c1.image-c2.image);
}
Complex operator * (const Complex &c1,const Complex &c2){
	return Complex(c1.real*c2.real-c1.image*c2.image,c1.real*c2.image+c1.image*c2.real);
}
int rev(int id,int len){
    int ret=0;
    for(int i=0;(1<<i)<len;++i){
		ret<<=1;
		if(id&(1<<i)){
			ret|=1;
		}
	}
	return ret;
}
Complex tmp[200100];
//μ±DFT==1ê±ê?DFT, DFT==-1ê±?òê???DFT
void IterativeFFT(Complex A[],int len, int DFT){//??3¤?è?alen(2μ??Y)μ?êy×é??DDDFT±???
	for(int i=0;i<len;++i){
		tmp[rev(i,len)]=A[i];
	}
	for(int i=0;i<len;++i){
		A[i]=tmp[i];
	}
	for(int s=1;(1<<s)<=len;++s){
		int m=(1<<s);
		Complex wm=Complex(cos(DFT*2*PI/m),sin(DFT*2*PI/m));
		for(int k=0;k<len;k+=m){//?aò?2??áμ?°üo?μ?êy×é?a????êy??ê?(1<<s)
			Complex w=Complex(1,0);
			for(int j=0;j<(m>>1);++j){//??°?òyàí£??ù?Yá???×ó?úμ????????úμ?
				Complex t=w*A[k+j+(m>>1)];
				Complex u=A[k+j];
				A[k+j]=u+t;
				A[k+j+(m>>1)]=u-t;
				w=w*wm;
			}
		}
	}
	if(DFT==-1){
		for(int i=0;i<len;++i){
			A[i].real/=len;
			A[i].image/=len;
		}
	}
}
Complex a[200100],b[200100];
int ans[200100];
char s1[50010],s2[50010];
int main(){
//	freopen("a.in","r",stdin);
	while(scanf("%s%s",s1,s2)!=EOF){
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		memset(ans,0,sizeof(ans));
		int len1=strlen(s1),len2=strlen(s2),len;
		if((len1==1 && s1[0]==‘0‘) || (len2==1 && s2[0]==‘0‘)){
			puts("0");
			continue;
		}
		for(int i=0;;++i){
			if((1<<i)>=len1+len2){
				len=(1<<i);
				break;
			}
		}
		for(int i=len1-1,j=0;i>=0;--i,++j){
			a[j]=Complex(s1[i]-‘0‘,0);
		}
		for(int i=len2-1,j=0;i>=0;--i,++j){
			b[j]=Complex(s2[i]-‘0‘,0);
		}
		IterativeFFT(a,len,1);
		IterativeFFT(b,len,1);
		for(int i=0;i<len;++i){
			a[i]=a[i]*b[i];
		}
		IterativeFFT(a,len,-1);
		for(int i=0;i<len;++i){
			ans[i]=(int)(a[i].real+0.5);
		}
		for(int i=0;i<len1+len2-1;++i){
			ans[i+1]+=ans[i]/10;
			ans[i]%=10;
		}
		for(int i=len;i>=0;--i){
			if(ans[i]!=0){
				for(int j=i;j>=0;--j){
					printf("%d",ans[j]);
				}
				puts("");
				break;
			}
		}
	}
	return 0;
}
时间: 2024-11-17 21:13:53

【FFT】hdu1402 A * B Problem Plus的相关文章

【NTT】hdu1402 A * B Problem Plus

r·2^k+1 r k g 3 1 1 2 5 1 2 2 17 1 4 3 97 3 5 5 193 3 6 5 257 1 8 3 7681 15 9 17 12289 3 12 11 40961 5 13 3 65537 1 16 3 786433 3 18 10 5767169 11 19 3 7340033 7 20 3 23068673 11 21 3 104857601 25 22 3 167772161 5 25 3 469762049 7 26 3 998244353 119

【FFT】专题总结

学了若干天终于学(bei)会了传说中的法法塔 感觉也没那么难用嘛 fft快速傅里叶变换 在大表课件上写就是解决高精乘的工具 其实很有理有据 fft就是用复数的折半引理优化两个多项式相乘的高端东西 他能使O(n^2)的多项式相乘优化到O(nlogn) 听ak说这也是比较模板的东西 也就不去理解什么证明了(其实是我看了半天看不懂TAT) 贴个代码吧(史上最短总结233- -) 1 int bit_rev(int t,int n){ 2 int res=0; 3 for (int i=0;i<n;i+

【BZOJ3489】A simple rmq problem kd-tree

[BZOJ3489]A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直接输出0.我会采取一些措施强制在线. Input 第一行为两个整数N,M.M是询问数,N是序列的长度(N<=100000,M<=200000) 第二行为N个整数,描述这个序列{ai},其中所有1<=ai<=N 再下面M行,每

【POJ】3468 A Simple Problem with Integers ——线段树 成段更新 懒惰标记

A Simple Problem with Integers Time Limit:5000MS   Memory Limit:131072K Case Time Limit:2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each

【hoj】 1017 Joseph&#39;s problem II

这个是约瑟夫的另一个变型,变为总共有2*k个人,先是K个好人后是k个坏人,要求前k次都要杀坏人,即在杀掉第一个好人之前就要把所有的坏人都杀光,所以需要我们求出满足这个条件的最小的m值: 由约瑟夫的递归模型可以发现,我们因为他的递归是从最后杀的人递归到原有的人数,所以我们可以吧顺序反过来,等价于最后杀掉k个坏人,再杀好人,这样在递归的时候就是先知道起始位置(先杀的人),这样就能迭代,由有好人时是否杀的是坏人来判定这个m是否适合,如果k次后杀到了第k个坏人则说明这个m是适合的 参考:http://w

【hoj】1016 Joseph&#39;s problem I

约瑟夫问题是一个很经典的问题,描述的是n的人围成一圈,每次数到第m个人就会被淘汰,之后在淘汰的人开始在数起第m个人,这样下去只带还剩下1个人为胜利者,这个题是约瑟夫问题的变形,它每次裁定的标准不再是一个恒定的m而是按照素数表中的第i次淘汰第i个人,所以我们需要求出素数表才能知道裁定的次序,也才能求出剩下的人的序号 首先,对于约瑟夫原本的问题是可以对每次淘汰使用逐个列举,将这n个人每个人都列举,没有出局的话就计1直到数到还没淘汰的第m个,但是这样下来对于n值很大的情况就会很耗时间,所以一定会有别的

【CF903G】Yet Another Maxflow Problem 线段树

[CF903G]Yet Another Maxflow Problem 题意:一张图分为两部分,左边有n个点A,右边有m个点B,所有Ai->Ai+1有边,所有Bi->Bi+1有边,某些Ai->Bj有边,每条边都有一定的容量. 先要求你支持两种操作: 1.修改某条Ai->Ai+1的边的容量2.询问从A1到Bm的最大流 n,m<=100000,流量<=10^9 题解:很有思维含量的题. 首先,我们把求最大流变成求最小割.容易发现,我们最多只会割一条Ai->Ai+1的边

【POJ】2480 Longge&#39;s problem(欧拉函数)

题目 传送门:QWQ 分析 题意就是求∑gcd(i, N) 1<=i <=N.. 显然$ gcd(i,n) = x $时,必然$x|n$. 所以我们枚举一下n的约数,对于每个约数x,显然$ gcd(i/x,n/x)=1$ 所以我们计算一下n/x的欧拉函数就ok了. 联赛前刷水题qwq 代码 // #include <bits/stdc++.h> #include <cstdio> #include <cmath> #include <algorithm

【FFT】快速傅里叶变换

[FFT]快速傅里叶变换 一.复数 1.定义 复数:设 $a$,$b$ 为实数,$i^{2}=−1$ ,形如 $a+bi$ 的数叫复数,其中 $i$ 被称为虚数单位,复数域是目前已知最大的域 在复平面中,$x$ 代表实数,$y$ 轴(除原点外的点)代表虚数,从原点 $(0,0)$ 到 $(a,b)$ 的向量表示复数 $a+bi$ 模长:从原点 $(0,0)$ 到点 $(a,b)$ 的距离,即 $\sqrt{a^2+b^2}$ 幅角:假设以逆时针为正方向,从 $x$ 轴正半轴到已知向量的转角的有向