洛谷P1919 A*B problem 快速傅里叶变换模板 [FFT]

  题目传送门

A*B problem

题目描述

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

输入输出格式

输入格式:

 

第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。

 

输出格式:

 

输出一行,即x*y的结果。(注意判断前导0)

 

输入输出样例

输入样例#1:
1
3
4
输出样例#1:
12

说明

数据范围:

n<=60000

来源:bzoj2179

本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。

 


  分析:

  之前都是拿python水过这题的。今天学懂了FFT,特地来刷一波。<不会FFT的看这里>

  思路没什么讲的,就是FFT,不过注意前导零,还要注意有的位数上会大于10,需要处理。

  Code:

 

// luogu-judger-enable-o2
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const double pi=acos(-1.0);
const int N=5e5+7;
int n,m,L,c[N],r[N];
char ca[N],cb[N];
struct complex{
    double x;double y;
    complex(double xx=0,double yy=0){x=xx;y=yy;}
}w1[N],w2[N];
complex operator + (complex a,complex b){return complex(a.x+b.x,a.y+b.y);}
complex operator - (complex a,complex b){return complex(a.x-b.x,a.y-b.y);}
complex operator * (complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y);}
void FFT(complex *A,int flag)
{
    for(int i=0;i)
    if(i<r[i])swap(A[i],A[r[i]]);
    for(int i=1;i1){
        complex wn(cos(pi/i),flag*sin(pi/i));
        for(int j=0;j1)){
            complex w(1,0);
            for(int k=0;kwn){
                complex a=A[j+k],b=w*A[i+j+k];
                A[j+k]=a+b,A[i+j+k]=a-b;}
        }
    }
}
int main()
{
    scanf("%d",&n);n--;m=2*n;
    scanf("%s",ca);
    for(int i=0;i<=n;i++)w1[i].x=ca[n-i]-'0';
    scanf("%s",cb);
    for(int i=0;i<=n;i++)w2[i].x=cb[n-i]-'0';
    for(n=1;n<=m;n<<=1)++L;
    for(int i=0;i)
    r[i]=((r[i>>1]>>1)|((i&1)<<(L-1)));
    FFT(w1,1);FFT(w2,1);
    for(int i=0;i<=n;i++)w1[i]=w1[i]*w2[i];
    FFT(w1,-1);
    for(int i=0;i<=m;i++)c[i]=(int)(w1[i].x/n+0.5);
    for(int i=0;i<=m;i++)
    if(c[i]>=10){
        c[i+1]+=c[i]/10;c[i]%=10;
        if(i==m)m++;}
    while(m>0&&c[m]==0)m--;
    for(int i=m;i>=0;i--)printf("%d",c[i]);
    return 0;
}

 

转载于:https://www.cnblogs.com/cytus/p/9215645.html

你可能感兴趣的:(洛谷P1919 A*B problem 快速傅里叶变换模板 [FFT])