BZOJ 2179 [快速傅里叶变换 高精度乘法]
2179: FFT快速傅立叶
Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 3108 Solved: 1599
[Submit][Status][Discuss]
Description
Input
n<=60000
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=3e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
const double PI=acos(-);
struct Vector{
double x,y;
Vector(double a=,double b=):x(a),y(b){}
};
typedef Vector CD;
Vector operator +(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
Vector operator -(Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
Vector operator *(Vector a,Vector b){return Vector(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
Vector conj(Vector a){return Vector(a.x,-a.y);} struct FastFourierTransform{
int n,rev[N];
CD omega[N],omegaInv[N];
void ini(int m){
n=;
while(n<m) n<<=;
for(int k=;k<n;k++)
omega[k]=CD(cos(*PI/n*k),sin(*PI/n*k)),
omegaInv[k]=conj(omega[k]); int k=;
while((<<k)<n) k++;
for(int i=;i<n;i++){
int t=;
for(int j=;j<k;j++) if(i&(<<j)) t|=(<<(k-j-));
rev[i]=t;
}
}
void transform(CD *a,CD *omega){
for(int i=;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int l=;l<=n;l<<=){
int m=l>>;
for(CD *p=a;p!=a+n;p+=l)
for(int k=;k<m;k++){
CD t=omega[n/l*k]*p[k+m];
p[k+m]=p[k]-t;
p[k]=p[k]+t;
}
}
}
void DFT(CD *a,int flag){
if(flag==) transform(a,omega);
else{
transform(a,omegaInv);
for(int i=;i<n;i++) a[i].x/=(double)n;
}
}
void FFT(CD *a,CD *b,int m){
ini(m);
DFT(a,);DFT(b,);
for(int i=;i<n;i++) a[i]=a[i]*b[i];
DFT(a,-);
}
}fft; CD A[N],B[N];
int n,m,c[N];
char s1[N],s2[N];
int main(){
freopen("in","r",stdin);
n=read();m=n+n-;
scanf("%s%s",s1,s2);
for(int i=;i<n;i++) A[i].x=s1[n-i-]-'',B[i].x=s2[n-i-]-'';
fft.FFT(A,B,m);
for(int i=;i<m;i++) c[i]=int(A[i].x+0.5);//printf("c %d\n",c[i]);
for(int i=;i<m;i++) c[i+]+=c[i]/,c[i]%=;
while(c[m]) m++;
for(int i=m-;i>=;i--) printf("%d",c[i]); return ;
}
FFT 1880ms
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=3e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
const double PI=acos(-);
struct Vector{
double x,y;
Vector(double a=,double b=):x(a),y(b){}
};
typedef Vector CD;
Vector operator +(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
Vector operator -(Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
Vector operator *(Vector a,Vector b){return Vector(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);} struct FastFourierTransform{
int n,rev[N];
void ini(int m){
n=;
while(n<m) n<<=; int k=;
while((<<k)<n) k++;
for(int i=;i<n;i++){
int t=;
for(int j=;j<k;j++) if(i&(<<j)) t|=(<<(k-j-));
rev[i]=t;
}
}
void DFT(CD *a,int flag){
for(int i=;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int l=;l<=n;l<<=){
int m=l>>;
CD wn(cos(*PI/l),flag*sin(*PI/l));
for(CD *p=a;p!=a+n;p+=l){
CD w(,);
for(int k=;k<m;k++){
CD t=w*p[k+m];
p[k+m]=p[k]-t;
p[k]=p[k]+t;
w=w*wn;
}
}
}
if(flag==-) for(int i=;i<n;i++) a[i].x/=n;
}
void FFT(CD *a,CD *b,int m){
ini(m);
DFT(a,);DFT(b,);
for(int i=;i<n;i++) a[i]=a[i]*b[i];
DFT(a,-);
}
}fft;
CD A[N],B[N];
int n,m,c[N];
char s1[N],s2[N];
int main(){
freopen("in","r",stdin);
n=read();m=n+n-;
scanf("%s%s",s1,s2);
for(int i=;i<n;i++) A[i].x=s1[n-i-]-'',B[i].x=s2[n-i-]-'';
fft.FFT(A,B,m);
for(int i=;i<m;i++) c[i]=int(A[i].x+0.5);//printf("c %d\n",c[i]);
for(int i=;i<m;i++) c[i+]+=c[i]/,c[i]%=;
while(c[m]) m++;
for(int i=m-;i>=;i--) printf("%d",c[i]); return ;
}
递推w的方法 FFT 1260ms
当然了,用NNT也可以,然而输给了常数
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=3e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
ll P=,MOD=P;
ll Pow(ll a,ll b,ll MOD){
ll ans=;
for(;b;b>>=,a=a*a%MOD)
if(b&) ans=ans*a%MOD;
return ans;
}
struct NumberTheoreticTransform{
int n,rev[N];
ll g;
void ini(int m){
n=;
while(n<m) n<<=; int k=;
while((<<k)<n) k++;
for(int i=;i<n;i++){
int t=;
for(int j=;j<k;j++) if(i&(<<j)) t|=(<<(k-j-));
rev[i]=t;
} g=;
}
void DFT(ll *a,int flag){
for(int i=;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int l=;l<=n;l<<=){
int m=l>>;
ll wn=Pow(g,flag==?(P-)/l:P--(P-)/l,P);
for(ll *p=a;p!=a+n;p+=l){
ll w=;
for(int k=;k<m;k++){
ll t=w*p[k+m]%P;
p[k+m]=(p[k]-t+P)%P;
p[k]=(p[k]+t)%P;
w=w*wn%P;
}
}
}
if(flag==-){
ll inv=Pow(n,P-,P);;
for(int i=;i<n;i++) a[i]=a[i]*inv%P;
}
}
void MUL(ll *A,ll *B){
DFT(A,);DFT(B,);
for(int i=;i<n;i++) A[i]=A[i]*B[i]%MOD;
DFT(A,-);
}
}fft;
int n,m,c[N];
char s1[N],s2[N];
ll A[N],B[N];
int main(){
freopen("in","r",stdin);
n=read();m=n+n-;
scanf("%s%s",s1,s2);
for(int i=;i<n;i++) A[i]=s1[n-i-]-'',B[i]=s2[n-i-]-'';
fft.ini(m);
fft.MUL(A,B);
for(int i=;i<m;i++) c[i]=A[i];//printf("c %d\n",c[i]);
for(int i=;i<m;i++) c[i+]+=c[i]/,c[i]%=;
while(c[m]) m++;
for(int i=m-;i>=;i--) printf("%d",c[i]);
}
NNT 3728ms
BZOJ 2179 [快速傅里叶变换 高精度乘法]的更多相关文章
- BZOJ 2194 [快速傅里叶变换 卷积]
题意:请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5. a,b中的元素均为小于等于100的非负整数. 卷积 ( ...
- BZOJ 2179 FFT快速傅立叶 题解
bzoj 2179 Description 给出两个n位10进制整数x和y,你需要计算x*y. [题目分析] 高精裸题.练手. [代码] 1.手动高精 #include<cstdio> # ...
- BZOJ 2179 FFT快速傅立叶 ——FFT
[题目分析] 快速傅里叶变换用于高精度乘法. 其实本质就是循环卷积的计算,也就是多项式的乘法. 两次蝴蝶变换. 二进制取反化递归为迭代. 单位根的巧妙取值,是的复杂度成为了nlogn 范德蒙矩阵计算逆 ...
- 【POJ 1001】Exponentiation (高精度乘法+快速幂)
BUPT2017 wintertraining(15) #6A 题意 求\(R^n\) ( 0.0 < R < 99.999 )(0 < n <= 25) 题解 将R用字符串读 ...
- Algorithm: 多项式乘法 Polynomial Multiplication: 快速傅里叶变换 FFT / 快速数论变换 NTT
Intro: 本篇博客将会从朴素乘法讲起,经过分治乘法,到达FFT和NTT 旨在能够让读者(也让自己)充分理解其思想 模板题入口:洛谷 P3803 [模板]多项式乘法(FFT) 朴素乘法 约定:两个多 ...
- [学习笔记] 多项式与快速傅里叶变换(FFT)基础
引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积, 而代码量却非常小. 博主一年半前曾经因COGS的一 ...
- 快速傅里叶变换FFT& 数论变换NTT
相关知识 时间域上的函数f(t)经过傅里叶变换(Fourier Transform)变成频率域上的F(w),也就是用一些不同频率正弦曲线的加 权叠加得到时间域上的信号. \[ F(\omega)=\m ...
- 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】
原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...
- HDU 1402 A * B Problem Plus 快速傅里叶变换 FFT 多项式
http://acm.hdu.edu.cn/showproblem.php?pid=1402 快速傅里叶变换优化的高精度乘法. https://blog.csdn.net/ggn_2015/artic ...
随机推荐
- [Golang]一道考察defer与命名返回值的题目
题目 输出: 4 1 3 解释 当函数有可命名结果形参时,结果形参的初始值被设置为零值,函数的return语句会设置结果形参的值 当函数有可命名结果形参时,defer函数是可以修改它,然后再将它的值返 ...
- cesium编程入门(六)添加 3D Tiles,并调整位置,贴地
添加 3D Tiles,并调整位置 3D Tiles 是什么 3DTiles数据集是cesium小组AnalyticlGraphics与2016年3月定义的一种数据集,3DTiles数据集以分块.分级 ...
- TP5.0 excel 导入导出
引第三方的phpexcel类库放到 ThinkPHP\Library\Vendor\demo下,自己建的文件夹demo 再将Excel.class放到ThinkPHP\Library\Org\clas ...
- 查看三种MySQL字符集的方法
查看MySQL字符集的命令是我们经常会使用到的,下文就介绍了其中的三种查看MySQL字符集的命令,供您参考学习. 作者:佚名来源:互联网|2010-10-09 11:36 移动端 收藏 分享 CTO训 ...
- PhpStorm (强大的PHP开发环境)2017.2.4 附注册方法
http://www.oyksoft.com/soft/40722.html?pc=1 最新版PhpStorm 2017正式版改进了PHP 7支持,改进代码完成功能. PhpStorm 是最好的PHP ...
- socket编程--相关函数--sendto();read();
{1} 头文件:#include <sys/types.h> #include <sys/socket.h>定义函数:int sendto(int s, const voi ...
- ASP.net core 2.0.0 中 asp.net identity 2.0.0 的基本使用(一)—修改数据库连接
开发环境:vs2017 版本:15.3.5 项目环境:.net framework 4.6.1 模板asp.net core 2.0 Web应用程序(模型视图控制器) 身份验证:个人用户账号 ...
- BIGIP-LTM中的NAT和SNAT
http://250688049.blog.51cto.com/643101/1095880 一.NAT(Network Address Translation)网络地址转换1.NAT简介 NAT ...
- 有关linux下redis overcommit_memory的问题
公司的几台Redis服务器出现不明故障,查看Redis日志,发现如下提示: 1 [34145] 01 Jan 17:42:02 # WARNING overcommit_memory is set t ...
- 关于eclipse 与OpenCV 配置频繁报错的问题总结Program "C:/SDK/android-ndk-xxx/ndk-build.cmd" is not found in PATH报错的解决!
2018-01-3116:58:12 Program "C:/SDK/android-ndk-r8/ndk-build.cmd" is not found in PATH 今天这一 ...