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 ...
随机推荐
- [国嵌笔记][017][Makefile工程管理]
Makefile的用途 1.make能够使整个程序的编译.链接只需一个命令就可以完成 2.make的工作主要依赖于Makefile的文件.Makefile文件描述了整个程序的编译.链接等规则,使之自动 ...
- html日历(3)
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 安卓Acitivity的启动模式
活动的四大启动模式 Ps:除了standar模式外,其他启动模式都要在AndroidManifest.xml中设置 android:lauchMode的值 安卓活动的启动模式(LaunchMode)有 ...
- 使用phpMyAdmin批量修改Mysql数据表前缀的方法
多个网站共用一个Mysql数据库时,为使数据库管理不混乱,一般采用不同的网站使用不同前缀名的方式进行区分.而如何批量修改已有数据库的前缀名呢?全部导出修改后再导入?还是一个表一个表的修改?今天我要介绍 ...
- Laravel5中使用阿里大于(鱼)发送短信验证码
在做用户注册和个人中心的安全管理时,我实现借助第三方短信平台(阿里大于(鱼))在Laravel框架中进行手机验证的设置:阿里大于,是阿里通信旗下优质便捷的云通信服务平台,整合了三大运营商的通信能力,为 ...
- 百度地图API显示多个标注点带百度样式信息检索窗口的代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Node.js框架 —— Express
一.安装express 1.需先安装express-generator npm install -g express-generator 2.安装express npm install -g expr ...
- 实现LNMP
实现LNMP 环境: linux系统机器 A:一台N:nginx,ip:192.168.213.251 B:一台P:php-fpm,php-mysql ,ip:192.168.213.253 C:一台 ...
- cuda纹理内存的使用
CUDA纹理内存的访问速度比全局内存要快,因此处理图像数据时,使用纹理内存是一个提升性能的好方法. 贴一段自己写的简单的实现两幅图像加权和的代码,使用纹理内存实现. 输入:两幅图 lena, moon ...
- zTree节点重叠或者遮挡
ztree官网:http://www.treejs.cn/v3/api.php 问题:zTree节点重叠或者遮挡. 分析:由于zTree和bootstrap插件样式冲突导致的树重叠问题. 解决:设置z ...