P1919 【模板】A*B Problem升级版 /// FFT模板
2024-10-07 22:39:26
题目大意:
给定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 ;
}
最新文章
- TinyFox v2.3.2 正式发布,跨平台的.NET OWIN WEB服务器
- CF467 AB 水题
- 利用Spring创建定时任务
- openfire教程网
- iOS开发——UI篇Swift篇&;玩转UItableView(三)分组功能
- 数据交互 ajax代码整理
- sqlite数据库修改及升级
- O-C相关-03:面向对象概念的具体介绍
- iOS内存管理系列之二:自动释放与便捷方法
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(18)-权限管理系统-表数据
- 网页动态切换母版页(MasterPage)
- android 使用Vysor投影到电脑
- AutoCAD 2019 for Mac 特别版(附注册机)
- mysql导入本地文件(作业)
- vue.js 添加 fastclick的支持
- 【LeetCode OJ】Majority Element
- ASP.NET MVC View使用Conditional compilation symbols
- 使用ksync 加速基于k8s 的应用开发
- AngularX Http服务总结
- System.Security.Cryptography.CryptographicException: 系统找不到指定的文件
热门文章
- 关于元素的offsetHeight、line-htight
- Java——super关键字
- js条件语句,用if...else if....else方程ax2+bx+c=0一元二次方程。求根
- 思维题+贪心——牛客多校第一场C
- [JZOJ 5810] 简单的玄学
- Codeforces786B
- TCP/IP点滴
- 17-MySQL-Ubuntu-数据表的查询-分页(六)
- Spring MVC @PathVariable注解(3)
- Nginx+win10安装配置