FFT

2 篇文章 0 订阅
1 篇文章 0 订阅

感觉也不是很会FFT,先把板子敲会再说吧= =

两条模板题_(:зゝ∠)_

UOJ #34

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define f(i,n) for (int i=0;i<n;i++)

const int N=4*1e5+5;
const double pi=acos(-1);
int n,m,k,ans[N]; 
struct CP{
	double x,y;
	CP operator +(const CP &A)const{
		return (CP){x+A.x,y+A.y};
	}
	CP operator -(const CP &A)const{
		return (CP){x-A.x,y-A.y};
	} 
	CP operator *(const CP &A)const{
		return (CP){x*A.x-y*A.y,x*A.y+y*A.x};
	}
}a[N],b[N];

void FFT(CP a[],int flag){
	for (int i=1,j=0;i<k-1;i++){
		for (int s=k;(~j)&s;j^=(s>>=1));
		if (i<j) swap(a[i],a[j]);
	}
	for (int i=2;i<=k;i<<=1){
		CP wn=(CP){cos(2*pi/i),flag*sin(2*pi/i)};
		for (int j=0;j<k;j+=i){
			CP w=(CP){1,0};
			for (int t=j;t<j+i/2;t++){
				CP x=a[t],y=a[t+i/2]*w;
				a[t]=x+y;a[t+i/2]=x-y;
				w=w*wn;
			}
		}
	}
	if (flag==1) return;
	f(i,k) a[i].x/=k; 
}

int main(){ 
	//freopen("34.in","r",stdin);
	scanf("%d%d",&n,&m);
	n++;m++;
	int x; 
	f(i,n) {
		scanf("%d",&x);
		a[i].x=x;
	}
	f(i,m) {
		scanf("%d",&x);
		b[i].x=x;
	}
	for (k=1;k<(n+m);k<<=1);
	FFT(a,1);FFT(b,1);
	f(i,k) a[i]=a[i]*b[i];
	FFT(a,-1);
	f(i,k) ans[i]=(int)(a[i].x+0.5);
	f(i,n+m-1)
		printf("%d%c",ans[i],i==n+m-2?'\n':' ');
	return 0; 
}

BZOJ 2179

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
#define f(i,x) for (int i=0;i<x;i++)

const int N=3*1e5;
const double pi=acos(-1);
int n,m,t,ans[N],len;
struct CP{
	double x,y;
	CP operator +(const CP &A)const
	{return (CP){x+A.x,y+A.y};}
	CP operator -(const CP &A)const
	{return (CP){x-A.x,y-A.y};}
	CP operator *(const CP &A)const
	{return (CP){x*A.x-y*A.y,x*A.y+y*A.x};}
}A[N],B[N];

void fft(CP a[],int flag){
	for (int i=1,j=0;i<t-1;i++){
		for (int s=t;(~j)&s;j^=(s>>=1));
		if (i<j) swap(a[i],a[j]);
	}
	for (int i=2;i<=t;i<<=1){
		CP wn=(CP){cos(2*pi/i),flag*sin(2*pi/i)};
		for (int j=0;j<t;j+=i){
			CP w=(CP){1,0};
			for (int k=j;k<j+i/2;k++){
				CP x=a[k],y=a[k+i/2]*w;
				a[k]=x+y;a[k+i/2]=x-y;
				w=w*wn;
			} 
		} 
	}
	if (flag==1) return ;
	f(i,t) a[i].x/=t;
}

int main(){
	scanf("%d\n",&n);
	for (t=1;t<=n+n;t<<=1);
	f(i,n){
		int x=getchar()-'0';
		A[n-i-1].x=x;
	}
	getchar();
	f(i,n){
		int x=getchar()-'0';
		B[n-i-1].x=x;
	}
	fft(A,1);fft(B,1);
	f(i,t) A[i]=A[i]*B[i];
	fft(A,-1);
	f(i,t) ans[i]+=(int)(A[i].x+0.5);
	f(i,n+n) if (ans[i]){
		len=i;
		ans[i+1]+=ans[i]/10;
		ans[i]%=10; 
	}
	for (int i=len;i>=0;i--) printf("%d",ans[i]);
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值