ZeroJudge h386 - Apples and Bananas 解題心得( 題目 )

解題概念:FFT(Fast Fourier Transform)

**這題本來是CSES題目,但是因為時限很緊,除C、C++之外的大部分語言都會被卡常,還好ZJ上有放寬時限的版本。

解題方法:這題如果硬做,是O(N^2),顯然不好,那我們可以試著把它換成多項式的題目嗎?

如果我們把令ax^b代表b重量的水果有a個,那我們把蘋果和香蕉分開做,得到兩個多項式,你會發現乘起來的結果,次方x的係數y其實就是代表總和重量x的組合有y個!

然而,把它當成多項式來做時間複雜度並沒有變好,還是O(N^2)......。

這裡就換FFT派上用場了(建議不會的讀者可以試著學看看,連結,先備知識:虛/複數平面、多項式基本常識),利用FFT可在O(NlogN)的時間內得到兩個多項式的乘積,藉此這題可以降到O(NlogN)。

Java參考程式碼(有更好意見可留言於下方,謝謝!):

//Author:En Chi Tsung(欉恩祁)

//Date:2022/03/15

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

public class zjh386 {

    public static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

    public static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));

    public static int ret,rd;

    public static long floor;

    public static final int N=1<<19,P=19;

    public static Complex[] w=new Complex[N];

    public static void main(String[] args) throws Exception{

        final int k=readint();

        final int n=readint();

        final int m=readint();

        int[] apple=new int[N];

        int[] banana=new int[N];

        Complex[] a=new Complex[N];

        Complex[] b=new Complex[N];

        Complex[] c=new Complex[N];

        double d;

        final double e=(2*Math.PI/N);

        for(int i=0;i<n;i++) {

            apple[readint()]++;

        }

        for(int i=0;i<m;i++) {

            banana[readint()]++;

        }

        for(int i=0;i<N;i++) {

            a[i]=new Complex(apple[i],0);

            b[i]=new Complex(banana[i],0);

            d=e*i;

            w[i]=new Complex(Math.cos(d),Math.sin(d));

        }

        FFT(a);

        FFT(b);

        for(int i=0;i<N;i++) {

            c[i]=multiply(a[i],b[i]);

            d=-e*i;

            w[i]=new Complex(Math.cos(d),Math.sin(d));

        }

        FFT(c);

        for(int i=2;i<=(k<<1);i++) {

            bw.write(round(c[i].r/N)+" ");

        }

        bw.write("\n");

        bw.flush();

    }

    

    public static void FFT(Complex[] in) {

        Complex o;

        int u,y;

        for(int i=0;i<N;i++) {

            u=0;

            for(int j=0;j<P;j++) {

                y=(1<<j);

                if((y&i)==y) {

                    u|=(1<<(P-1-j));

                }

            }

            if(i<u) {

                o=in[i];//swap

                in[i]=in[u];

                in[u]=o;

            }

        }

        for(int i=1;i<N;i<<=1) {

            for(int j=0;j<N;j+=(i<<1)) {

                for(int k=j;k<i+j;k++) {

                    o=multiply(in[i+k],w[(int)((long)(k-j)*N/i>>1)]);

                    in[i+k]=minus(in[k],o);

                    in[k]=plus(in[k],o);

                }

            }

        }

    }

    

    public static Complex plus(Complex a,Complex b) {

        return new Complex(a.r+b.r,a.i+b.i);

    }

    

    public static Complex minus(Complex a,Complex b) {

        return new Complex(a.r-b.r,a.i-b.i);

    }

    

    public static Complex multiply(Complex a,Complex b) {

        return new Complex(a.r*b.r-a.i*b.i,a.i*b.r+a.r*b.i);

    }

    

    public static long round(double x) {

        floor=(long)x;

        if(x-floor>0.5) {

            return floor+1;

        }

        return floor;

    }



    public static int readint() throws Exception{

        ret=0;

        rd=br.read();

        while(rd>47&&rd<58) {

            ret*=10;

            ret+=(rd&15);

            rd=br.read();

        }

        return ret;

    }

}



class Complex{

    double r,i;

    Complex(double real,double imag){

        r=real;

        i=imag;

    }

}

 

 

 

 

文章標籤
全站熱搜
創作者介紹
創作者 En Chi Tsung 的頭像
En Chi Tsung

阿祁的部落格

En Chi Tsung 發表在 痞客邦 留言(0) 人氣(3)