2179: FFT快速傅立叶

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 3108  Solved: 1599
[Submit][Status][Discuss]

Description

给出两个n位10进制整数x和y,你需要计算x*y。

Input

第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。
 
数据范围:
n<=60000

扔个模板
注意读入字符转换成系数 系数转换成整数
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <cmath>
  6. using namespace std;
  7. const int N=3e5+;
  8. inline int read(){
  9. char c=getchar();int x=,f=;
  10. while(c<''||c>''){if(c=='-')f=-;c=getchar();}
  11. while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
  12. return x*f;
  13. }
  14. const double PI=acos(-);
  15. struct Vector{
  16. double x,y;
  17. Vector(double a=,double b=):x(a),y(b){}
  18. };
  19. typedef Vector CD;
  20. Vector operator +(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
  21. Vector operator -(Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
  22. Vector operator *(Vector a,Vector b){return Vector(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
  23. Vector conj(Vector a){return Vector(a.x,-a.y);}
  24.  
  25. struct FastFourierTransform{
  26. int n,rev[N];
  27. CD omega[N],omegaInv[N];
  28. void ini(int m){
  29. n=;
  30. while(n<m) n<<=;
  31. for(int k=;k<n;k++)
  32. omega[k]=CD(cos(*PI/n*k),sin(*PI/n*k)),
  33. omegaInv[k]=conj(omega[k]);
  34.  
  35. int k=;
  36. while((<<k)<n) k++;
  37. for(int i=;i<n;i++){
  38. int t=;
  39. for(int j=;j<k;j++) if(i&(<<j)) t|=(<<(k-j-));
  40. rev[i]=t;
  41. }
  42. }
  43. void transform(CD *a,CD *omega){
  44. for(int i=;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
  45. for(int l=;l<=n;l<<=){
  46. int m=l>>;
  47. for(CD *p=a;p!=a+n;p+=l)
  48. for(int k=;k<m;k++){
  49. CD t=omega[n/l*k]*p[k+m];
  50. p[k+m]=p[k]-t;
  51. p[k]=p[k]+t;
  52. }
  53. }
  54. }
  55. void DFT(CD *a,int flag){
  56. if(flag==) transform(a,omega);
  57. else{
  58. transform(a,omegaInv);
  59. for(int i=;i<n;i++) a[i].x/=(double)n;
  60. }
  61. }
  62. void FFT(CD *a,CD *b,int m){
  63. ini(m);
  64. DFT(a,);DFT(b,);
  65. for(int i=;i<n;i++) a[i]=a[i]*b[i];
  66. DFT(a,-);
  67. }
  68. }fft;
  69.  
  70. CD A[N],B[N];
  71. int n,m,c[N];
  72. char s1[N],s2[N];
  73. int main(){
  74. freopen("in","r",stdin);
  75. n=read();m=n+n-;
  76. scanf("%s%s",s1,s2);
  77. for(int i=;i<n;i++) A[i].x=s1[n-i-]-'',B[i].x=s2[n-i-]-'';
  78. fft.FFT(A,B,m);
  79. for(int i=;i<m;i++) c[i]=int(A[i].x+0.5);//printf("c %d\n",c[i]);
  80. for(int i=;i<m;i++) c[i+]+=c[i]/,c[i]%=;
  81. while(c[m]) m++;
  82. for(int i=m-;i>=;i--) printf("%d",c[i]);
  83.  
  84. return ;
  85. }

FFT 1880ms

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <cmath>
  6. using namespace std;
  7. const int N=3e5+;
  8. inline int read(){
  9. char c=getchar();int x=,f=;
  10. while(c<''||c>''){if(c=='-')f=-;c=getchar();}
  11. while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
  12. return x*f;
  13. }
  14. const double PI=acos(-);
  15. struct Vector{
  16. double x,y;
  17. Vector(double a=,double b=):x(a),y(b){}
  18. };
  19. typedef Vector CD;
  20. Vector operator +(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
  21. Vector operator -(Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
  22. Vector operator *(Vector a,Vector b){return Vector(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
  23.  
  24. struct FastFourierTransform{
  25. int n,rev[N];
  26. void ini(int m){
  27. n=;
  28. while(n<m) n<<=;
  29.  
  30. int k=;
  31. while((<<k)<n) k++;
  32. for(int i=;i<n;i++){
  33. int t=;
  34. for(int j=;j<k;j++) if(i&(<<j)) t|=(<<(k-j-));
  35. rev[i]=t;
  36. }
  37. }
  38. void DFT(CD *a,int flag){
  39. for(int i=;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
  40. for(int l=;l<=n;l<<=){
  41. int m=l>>;
  42. CD wn(cos(*PI/l),flag*sin(*PI/l));
  43. for(CD *p=a;p!=a+n;p+=l){
  44. CD w(,);
  45. for(int k=;k<m;k++){
  46. CD t=w*p[k+m];
  47. p[k+m]=p[k]-t;
  48. p[k]=p[k]+t;
  49. w=w*wn;
  50. }
  51. }
  52. }
  53. if(flag==-) for(int i=;i<n;i++) a[i].x/=n;
  54. }
  55. void FFT(CD *a,CD *b,int m){
  56. ini(m);
  57. DFT(a,);DFT(b,);
  58. for(int i=;i<n;i++) a[i]=a[i]*b[i];
  59. DFT(a,-);
  60. }
  61. }fft;
  62. CD A[N],B[N];
  63. int n,m,c[N];
  64. char s1[N],s2[N];
  65. int main(){
  66. freopen("in","r",stdin);
  67. n=read();m=n+n-;
  68. scanf("%s%s",s1,s2);
  69. for(int i=;i<n;i++) A[i].x=s1[n-i-]-'',B[i].x=s2[n-i-]-'';
  70. fft.FFT(A,B,m);
  71. for(int i=;i<m;i++) c[i]=int(A[i].x+0.5);//printf("c %d\n",c[i]);
  72. for(int i=;i<m;i++) c[i+]+=c[i]/,c[i]%=;
  73. while(c[m]) m++;
  74. for(int i=m-;i>=;i--) printf("%d",c[i]);
  75.  
  76. return ;
  77. }

递推w的方法 FFT 1260ms

当然了,用NNT也可以,然而输给了常数

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <cmath>
  6. using namespace std;
  7. typedef long long ll;
  8. const int N=3e5+;
  9. inline int read(){
  10. char c=getchar();int x=,f=;
  11. while(c<''||c>''){if(c=='-')f=-;c=getchar();}
  12. while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
  13. return x*f;
  14. }
  15. ll P=,MOD=P;
  16. ll Pow(ll a,ll b,ll MOD){
  17. ll ans=;
  18. for(;b;b>>=,a=a*a%MOD)
  19. if(b&) ans=ans*a%MOD;
  20. return ans;
  21. }
  22. struct NumberTheoreticTransform{
  23. int n,rev[N];
  24. ll g;
  25. void ini(int m){
  26. n=;
  27. while(n<m) n<<=;
  28.  
  29. int k=;
  30. while((<<k)<n) k++;
  31. for(int i=;i<n;i++){
  32. int t=;
  33. for(int j=;j<k;j++) if(i&(<<j)) t|=(<<(k-j-));
  34. rev[i]=t;
  35. }
  36.  
  37. g=;
  38. }
  39. void DFT(ll *a,int flag){
  40. for(int i=;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
  41. for(int l=;l<=n;l<<=){
  42. int m=l>>;
  43. ll wn=Pow(g,flag==?(P-)/l:P--(P-)/l,P);
  44. for(ll *p=a;p!=a+n;p+=l){
  45. ll w=;
  46. for(int k=;k<m;k++){
  47. ll t=w*p[k+m]%P;
  48. p[k+m]=(p[k]-t+P)%P;
  49. p[k]=(p[k]+t)%P;
  50. w=w*wn%P;
  51. }
  52. }
  53. }
  54. if(flag==-){
  55. ll inv=Pow(n,P-,P);;
  56. for(int i=;i<n;i++) a[i]=a[i]*inv%P;
  57. }
  58. }
  59. void MUL(ll *A,ll *B){
  60. DFT(A,);DFT(B,);
  61. for(int i=;i<n;i++) A[i]=A[i]*B[i]%MOD;
  62. DFT(A,-);
  63. }
  64. }fft;
  65. int n,m,c[N];
  66. char s1[N],s2[N];
  67. ll A[N],B[N];
  68. int main(){
  69. freopen("in","r",stdin);
  70. n=read();m=n+n-;
  71. scanf("%s%s",s1,s2);
  72. for(int i=;i<n;i++) A[i]=s1[n-i-]-'',B[i]=s2[n-i-]-'';
  73. fft.ini(m);
  74. fft.MUL(A,B);
  75. for(int i=;i<m;i++) c[i]=A[i];//printf("c %d\n",c[i]);
  76. for(int i=;i<m;i++) c[i+]+=c[i]/,c[i]%=;
  77. while(c[m]) m++;
  78. for(int i=m-;i>=;i--) printf("%d",c[i]);
  79. }

NNT 3728ms

BZOJ 2179 [快速傅里叶变换 高精度乘法]的更多相关文章

  1. BZOJ 2194 [快速傅里叶变换 卷积]

    题意:请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5. a,b中的元素均为小于等于100的非负整数. 卷积 ( ...

  2. BZOJ 2179 FFT快速傅立叶 题解

    bzoj 2179 Description 给出两个n位10进制整数x和y,你需要计算x*y. [题目分析] 高精裸题.练手. [代码] 1.手动高精 #include<cstdio> # ...

  3. BZOJ 2179 FFT快速傅立叶 ——FFT

    [题目分析] 快速傅里叶变换用于高精度乘法. 其实本质就是循环卷积的计算,也就是多项式的乘法. 两次蝴蝶变换. 二进制取反化递归为迭代. 单位根的巧妙取值,是的复杂度成为了nlogn 范德蒙矩阵计算逆 ...

  4. 【POJ 1001】Exponentiation (高精度乘法+快速幂)

    BUPT2017 wintertraining(15) #6A 题意 求\(R^n\) ( 0.0 < R < 99.999 )(0 < n <= 25) 题解 将R用字符串读 ...

  5. Algorithm: 多项式乘法 Polynomial Multiplication: 快速傅里叶变换 FFT / 快速数论变换 NTT

    Intro: 本篇博客将会从朴素乘法讲起,经过分治乘法,到达FFT和NTT 旨在能够让读者(也让自己)充分理解其思想 模板题入口:洛谷 P3803 [模板]多项式乘法(FFT) 朴素乘法 约定:两个多 ...

  6. [学习笔记] 多项式与快速傅里叶变换(FFT)基础

    引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积, 而代码量却非常小. 博主一年半前曾经因COGS的一 ...

  7. 快速傅里叶变换FFT& 数论变换NTT

    相关知识 时间域上的函数f(t)经过傅里叶变换(Fourier Transform)变成频率域上的F(w),也就是用一些不同频率正弦曲线的加 权叠加得到时间域上的信号. \[ F(\omega)=\m ...

  8. 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】

    原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...

  9. HDU 1402 A * B Problem Plus 快速傅里叶变换 FFT 多项式

    http://acm.hdu.edu.cn/showproblem.php?pid=1402 快速傅里叶变换优化的高精度乘法. https://blog.csdn.net/ggn_2015/artic ...

随机推荐

  1. [国嵌笔记][017][Makefile工程管理]

    Makefile的用途 1.make能够使整个程序的编译.链接只需一个命令就可以完成 2.make的工作主要依赖于Makefile的文件.Makefile文件描述了整个程序的编译.链接等规则,使之自动 ...

  2. html日历(3)

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  3. 安卓Acitivity的启动模式

    活动的四大启动模式 Ps:除了standar模式外,其他启动模式都要在AndroidManifest.xml中设置 android:lauchMode的值 安卓活动的启动模式(LaunchMode)有 ...

  4. 使用phpMyAdmin批量修改Mysql数据表前缀的方法

    多个网站共用一个Mysql数据库时,为使数据库管理不混乱,一般采用不同的网站使用不同前缀名的方式进行区分.而如何批量修改已有数据库的前缀名呢?全部导出修改后再导入?还是一个表一个表的修改?今天我要介绍 ...

  5. Laravel5中使用阿里大于(鱼)发送短信验证码

    在做用户注册和个人中心的安全管理时,我实现借助第三方短信平台(阿里大于(鱼))在Laravel框架中进行手机验证的设置:阿里大于,是阿里通信旗下优质便捷的云通信服务平台,整合了三大运营商的通信能力,为 ...

  6. 百度地图API显示多个标注点带百度样式信息检索窗口的代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. Node.js框架 —— Express

    一.安装express 1.需先安装express-generator npm install -g express-generator 2.安装express npm install -g expr ...

  8. 实现LNMP

    实现LNMP 环境: linux系统机器 A:一台N:nginx,ip:192.168.213.251 B:一台P:php-fpm,php-mysql ,ip:192.168.213.253 C:一台 ...

  9. cuda纹理内存的使用

    CUDA纹理内存的访问速度比全局内存要快,因此处理图像数据时,使用纹理内存是一个提升性能的好方法. 贴一段自己写的简单的实现两幅图像加权和的代码,使用纹理内存实现. 输入:两幅图 lena, moon ...

  10. zTree节点重叠或者遮挡

    ztree官网:http://www.treejs.cn/v3/api.php 问题:zTree节点重叠或者遮挡. 分析:由于zTree和bootstrap插件样式冲突导致的树重叠问题. 解决:设置z ...