zoukankan      html  css  js  c++  java
  • P1919 【模板】A*B Problem升级版(FFT快速傅里叶)

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

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

    说明

    数据范围:

    n<=60000

    来源:bzoj2179

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define maxn 240010
    #define PI (acos(-1.0))
    using namespace std;
    int rd[maxn],d[maxn<<1];
    char s[maxn];
    struct node{
        double x,y;
        node(double a=0,double b=0):x(a),y(b){}
        node operator + (const node &c)
        {return node(x+c.x,y+c.y);}
        node operator - (const node &c)
        {return node(x-c.x,y-c.y);}
        node operator * (const node &c)
        {return node(x*c.x-y*c.y,x*c.y+y*c.x);}
        node operator / (const int &c)
        {return node(x/c,y/c);}
    }a[maxn],b[maxn];
    void fft(node *a,int n,int f){
        node wn,w,x,y;int i;
        for(int i=0;i<=n;i++)if(rd[i]>i)swap(a[i],a[rd[i]]);
        for(int k=1;k<n;k<<=1){
            wn=node(cos(PI/k),f*sin(PI/k));
            for(int j=0;j<n;j+=k<<1){
                for(w=node(1,0),i=0;i<k;i++,w=w*wn){
                    node x=a[i+j];
                    node y=a[i+j+k]*w;
                    a[i+j]=x+y;
                    a[i+j+k]=x-y;
                }
            }
        }
        if(f==-1)
            for(int i=0;i<n;i++)a[i]=a[i]/n;
    }
    int main(){
        freopen("testdata.in","r",stdin);
        int n;
        scanf("%d",&n);n--;
        scanf("%s",s);
        for(int i=0;i<=n;i++)a[i].x=s[i]-'0';
        scanf("%s",s);
        for(int i=0;i<=n;i++)b[i].x=s[i]-'0';
        int m=n+n,l=0;n=1;
        while(n<=m)n<<=1,l++;
        for(int i=0;i<=n;i++)rd[i]=(rd[i>>1]>>1)|((i&1)<<(l-1));
        fft(a,n,1);fft(b,n,1);
        for(int i=0;i<=n;i++)a[i]=a[i]*b[i];
        fft(a,n,-1);
        for(int i=1,j=m+1;i<=m+1;i++,j--)
            d[j]=(int)(a[i-1].x+0.5);
        for(int i=1;i<=n;i++)d[i+1]+=d[i]/10,d[i]%=10;
        while(!d[n]&&n)n--;
        if(n!=0)for(int i=n;i>=1;i--)printf("%d",d[i]);
        else puts("0");
        return 0;
    }
  • 相关阅读:
    java使用递归删除非空目录
    关于Java日期的两道例题
    equals和==的区别
    从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为0时结束程序。
    输出所有的水仙花数
    99乘法表
    switch
    next()、nextInt()
    流程控制
    Scanner从键盘输入
  • 原文地址:https://www.cnblogs.com/thmyl/p/8798996.html
Copyright © 2011-2022 走看看