P1919 【模板】A*B Problem升级版 /// FFT模板
题目大意:
给定l,输入两个位数为l的数A B
输出两者的乘积
FFT讲解 这个讲解蛮好的 就是讲解里面贴的模板是错误的
struct cpx {
double x,y;
cpx(double _x=0.0,double _y=0.0) {
x=_x; y=_y;
}
cpx operator -(const cpx &b) const {
return cpx(x-b.x,y-b.y);
}
cpx operator +(const cpx &b) const {
return cpx(x+b.x,y+b.y);
}
cpx operator *(const cpx &b) const {
return cpx(x*b.x-y*b.y,x*b.y+y*b.x);
}
};
void change(cpx a[],int len) /// 位置互换 len必须是2的幂
{
for(int i=,j=len/;i<len-;i++) {
if(i<j) swap(a[i],a[j]);
int k=len/;
while(j>=k) j-=k, k>>=;
if(j<k) j+=k;
}
}
#define PI acos(-1)
void fft(cpx a[],int len,int on)/// len必须是2的幂 on为1时dft -1时idft
{
change(a,len);
for(int i=;i<len;i <<= ) {
cpx wn(cos(PI/i),on*sin(PI/i));
for(int j=;j<len;j+=(i<<)) {
cpx w(,);
for(int k=;k<i;k++,w=w*wn) {
cpx u=a[j+k], v=w*a[j+k+i];
a[j+k]=u+v, a[j+k+i]=u-v;
}
}
}
if(on==-) {
for(int i=;i<len;i++)
a[i].x/=len;
}
}
FFT模板1
struct cpx {
double x,y;
cpx(double _x=0.0,double _y=0.0) {
x=_x; y=_y;
}
cpx operator - (const cpx &b)const {
return cpx(x-b.x,y-b.y);
}
cpx operator + (const cpx &b)const {
return cpx(x+b.x,y+b.y);
}
cpx operator * (const cpx &b)const {
return cpx(x*b.x-y*b.y,x*b.y+y*b.x);
}
};
void fft(cpx a[],int on)
{
for(int i=;i<len;i++)
if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=;i<len;i<<=) {
cpx wn(cos(PI/i),on*sin(PI/i));
for(int j=;j<len;j+=(i<<)) {
cpx w(,);
for(int k=;k<i;k++,w=w*wn) {
cpx u=a[j+k], v=w*a[j+k+i];
a[j+k]=u+v, a[j+k+i]=u-v;
}
}
}
}
int main()
{
......
while(len<d*) len <<= , l++; // 将长度补到2的幂
for(int i=;i<len;i++)
r[i]=( r[i>>]>> )|( (i&)<<(l-) );
......
}
FFT模板2
这题是把两个数看成
A=a1*10^0+a2*10^1+a3*10^2...+al*10^(l-1)
B=b1*10^0+b2*10^1+b3*10^2...+bl*10^(l-1)
的形式
这样就变成了多项式相乘
#include <bits/stdc++.h>
#define PI acos(-1)
#define MAXN 300004
using namespace std; struct cpx{
double x,y;
cpx(double _x=0.0,double _y=0.0) {
x=_x; y=_y;
}
cpx operator-(const cpx &b)const {
return cpx(x-b.x,y-b.y);
}
cpx operator+(const cpx &b)const {
return cpx(x+b.x,y+b.y);
}
cpx operator*(const cpx &b)const {
return cpx(x*b.x-y*b.y,x*b.y+y*b.x);
}
}x1[MAXN/], x2[MAXN/]; char str1[MAXN/], str2[MAXN/];
int sum[MAXN], l; void change(cpx a[],int len) /// 位置互换 len必须是2的幂
{
for(int i=,j=len/;i<len-;i++) {
if(i<j) swap(a[i],a[j]);
int k=len/;
while(j>=k) {
j-=k, k >>= ;
}
if(j<k) j+=k;
}
} void fft(cpx a[],int len,int on)/// len必须是2的幂 on为1时dft -1时idft
{
change(a,len);
for(int i=;i<len;i <<= ) {
cpx wn(cos(PI/i),on*sin(PI/i));
for(int j=;j<len;j+=(i<<)) {
cpx w(,);
for(int k=;k<i;k++,w=w*wn) {
cpx u=a[j+k], t=w*a[j+k+i];
a[j+k]=u+t, a[j+k+i]=u-t;
}
}
}
if(on==-) {
for(int i=;i<len;i++)
a[i].x/=len;
}
} int main()
{
while(~scanf("%d",&l)) {
scanf("%s%s",str1,str2);
int len=;
while(len<l*) len <<= ; // 将长度补到2的幂
for(int i=;i<l;i++)
x1[i]=cpx(str1[l--i]-'',),
x2[i]=cpx(str2[l--i]-'',);
for(int i=l;i<len;i++)
x1[i]=x2[i]=cpx(,); // 不足补0 fft(x1,len,); fft(x2,len,); /// dft转为点值表达
for(int i=;i<len;i++) x1[i]=x1[i]*x2[i]; // 计算
fft(x1,len,-); /// idft转为系数表达 for(int i=;i<len;i++)
sum[i]=(int)(x1[i].x+0.1); // 四舍五入
for(int i=;i<len;i++)
sum[i+]+=sum[i]/, sum[i]%=; // 进制
while(sum[len]== && len>) len--; // 去前导0
for(int i=len;i>=;i--)
printf("%d",sum[i]); printf("\n");
} return ;
}
两种模板的细节区别在于
(2)在四舍五入时除len ,而(1)是在FFT中判断开关on再除len
#include <bits/stdc++.h>
#define PI acos(-1.0)
const int MAXN=;
using namespace std; struct cpx {
double x,y;
cpx(double _x=0.0,double _y=0.0) {
x=_x; y=_y;
}
cpx operator - (const cpx &b)const {
return cpx(x-b.x,y-b.y);
}
cpx operator + (const cpx &b)const {
return cpx(x+b.x,y+b.y);
}
cpx operator * (const cpx &b)const {
return cpx(x*b.x-y*b.y,x*b.y+y*b.x);
}
}x1[MAXN], x2[MAXN]; int n, m, len=;
int l, r[MAXN], sum[MAXN];
char str1[MAXN],str2[MAXN]; void fft(cpx a[],int on)
{
for(int i=;i<len;i++)
if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=;i<len;i<<=) {
cpx wn(cos(PI/i),on*sin(PI/i));
for(int j=;j<len;j+=(i<<)) {
cpx w(,);
for(int k=;k<i;k++,w=w*wn) {
cpx u=a[j+k], v=w*a[j+k+i];
a[j+k]=u+v, a[j+k+i]=u-v;
}
}
}
} int main()
{
int d;
while(~scanf("%d",&d)) {
scanf("%s%s",str1,str2);
while(len<d*) len <<= , l++; // 将长度补到2的幂
for(int i=;i<d;i++)
x1[i]=cpx(str1[d--i]-'',),
x2[i]=cpx(str2[d--i]-'',);
for(int i=;i<len;i++)
r[i]=( r[i>>]>> )|( (i&)<<(l-) ); fft(x1,); fft(x2,); /// dft转为点值表达
for(int i=;i<len;i++) x1[i]=x1[i]*x2[i]; // 计算
fft(x1,-); /// idft转为系数表达 for(int i=;i<len;i++)
sum[i]=(int)(x1[i].x/len+0.1); // 四舍五入
for(int i=;i<len;i++)
sum[i+]+=sum[i]/, sum[i]%=; // 进制
while(sum[len]== && len>) len--; // 去前导0
for(int i=len;i>=;i--)
printf("%d",sum[i]); printf("\n");
} return ;
}
P1919 【模板】A*B Problem升级版 /// FFT模板的更多相关文章
- 洛谷.1919.[模板]A*B Problem升级版(FFT)
题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 ...
- HDU 1402 A * B Problem Plus (FFT模板题)
FFT模板题,求A*B. 用次FFT模板需要注意的是,N应为2的幂次,不然二进制平摊反转置换会出现死循环. 取出结果值时注意精度,要加上eps才能A. #include <cstdio> ...
- [hdu1402]A * B Problem Plus(FFT模板题)
解题关键:快速傅里叶变换fft练习. 关于结果多项式长度的确定,首先将短多项式扩展为长多项式,然后扩展为两倍. #include<cstdio> #include<cstring&g ...
- 【洛谷P1919】A*B Problem升级版
题目大意:rt 题解:将长度为 N 的大整数看作是一个 N-1 次的多项式,利用 FFT 计算多项式的卷积即可. 代码如下 #include <bits/stdc++.h> using n ...
- 洛谷P1919 【模板】A*B Problem升级版 题解(FFT的第一次实战)
洛谷P1919 [模板]A*B Problem升级版(FFT快速傅里叶) 刚学了FFT,我们来刷一道模板题. 题目描述 给定两个长度为 n 的两个十进制数,求它们的乘积. n<=100000 如 ...
- 再写FFT模板
没什么好说的,今天又考了FFT(虽然不用FFT也能过)但是确实有忘了怎么写FFT了,于是乎只有重新写一遍FFT模板练一下手了.第一部分普通FFT,第二部分数论FFT,记一下模数2^23*7*17+1 ...
- FFT模板(多项式乘法)
FFT模板(多项式乘法) 标签: FFT 扯淡 一晚上都用来捣鼓这个东西了...... 这里贴一位神犇的博客,我认为讲的比较清楚了.(刚好适合我这种复数都没学的) http://blog.csdn.n ...
- FFT/NTT总结+洛谷P3803 【模板】多项式乘法(FFT)(FFT/NTT)
前言 众所周知,这两个东西都是用来算多项式乘法的. 对于这种常人思维难以理解的东西,就少些理解,多背板子吧! 因此只总结一下思路和代码,什么概念和推式子就靠巨佬们吧 推荐自为风月马前卒巨佬的概念和定理 ...
- 2018.08.28 洛谷P3803 【模板】多项式乘法(FFT)
传送门 fft模板题. 终于学会fft了. 这个方法真是神奇! 经过试验发现手写的complex快得多啊! 代码: #include<iostream> #include<cstdi ...
随机推荐
- EasyUI - 简介
1. EasyUI : 简单的界面设计框架, 基于jQuery的UI插件, 主要用来设计网站的后台管理系统 2. EasyUI使用 : 将EasyUI提供的js文件和主题(themes)样式存放到项目 ...
- TStringGrid 实现下拉框
TStringGrid 实现下拉框比较常见的思路是在TSringGrid中嵌入一个TComboBox ,思路虽然简单,但开发起来却很麻烦,而且有时会出现不愿看到的效果.还有一种更巧的方法,是Delph ...
- js条件语句,用if...else if....else方程ax2+bx+c=0一元二次方程。求根
if 语句 - 只有当指定条件为 true 时,使用该语句来执行代码 if...else 语句 - 当条件为 true 时执行代码,当条件为 false 时执行其他代码 if...else if... ...
- 依赖背包变形——poj1947(经典)
/*这题显然不适用依赖背包的优化,因为不能保证根是必选的,但是可以按照常规依赖背包的思路进行转移,即每次对一个儿子进行C^2的转移 还是树形的背包,dp[u][j]表示u的子树里,切割出一个大小为j的 ...
- GetWindowLong
函数功能:该函数获得有关指定窗口的信息,函数也获得在额外窗口内存中指定偏移位地址的32位度整型值. 函数原型:LONG GetWindowLong(HWND hWnd,int nlndex): 参数: ...
- BZOJ 2159: Crash 的文明世界(组合数学+第二类斯特林数+树形dp)
传送门 解题思路 比较有意思的一道数学题.首先\(n*k^2\)的做法比较好想,就是维护一个\(x^i\)这种东西,然后转移的时候用二项式定理拆开转移.然后有一个比较有意思的结论就是把求\(x^i\) ...
- ssh 私钥和公钥 参考的linux就该这么学
- 数据结构C++版-队列
一.概念 分类: 二.补充说明 1.<面向对象的队列设计>课程问答: 首先要明确数据结构和数据存储结构的概念. 数据结构是指数据对象之间的逻辑关系,例如二叉树,队列,栈等,而数据存储结构是 ...
- day27-面向对象进阶
#!/usr/bin/env python # -*- coding:utf-8 -*- # ----------------------------------------------------- ...
- tensorflow TypeError: Can not convert a float32 into a Tensor or Operation
遇到这种情况可能是你的程序中有和你定义的tensor 变量重名的其他变量名字,jishi在for循环中使用了这个名字的作为临时变量也不行.tenor 变量很娇气.坑了我一晚上的时间. 比如:x = t ...