UVALive_6886_Golf Bot(FFT快速傅里叶变换)

来源:互联网 发布:时时彩源码程序出售 编辑:程序博客网 时间:2024/03/28 18:22

传送门:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=77958#problem/C


题型:数论


题意:

       集合A中取1个数或者2个数,其和变成一个新的集合S。q次查询,每次查询输入一个数,问q个数中有多少个数属于集合S。

      集合A元素个数2e5,q<=2e5,A元素大小<=2e5,查询数字2e5


分析:

暴力枚举O(C(n,2)+n),O(n^2)复杂度过高。

FFT统计出现了哪些数,然后直接算结果就ok,复杂度O(nlogn)。

只取1个数只需要O(n)标记一下,S1 = {1,3,5}。

下面讨论取2个数的情况:

例如A = {1,3,5}

设多项式


则S2 = {2,4,6,8,10}

综上:S={1,2,3,4,5,6,8,10}


代码;

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define mt(a,b) memset(a,b,sizeof(a))using namespace std;const int M = 201000;struct Complex {    double x,y;    Complex(double _x=0,double _y=0) {        x=_x;        y=_y;    }    friend Complex operator -(const Complex &a,const Complex &b) {        return Complex(a.x-b.x,a.y-b.y);    }    friend Complex operator +(const Complex &a,const Complex &b) {        return Complex(a.x+b.x,a.y+b.y);    }    friend Complex operator *(const Complex &a,const Complex &b) {        return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);    }};class FFT {    Complex u,t;    void change(Complex y[],int len) {        for(int i=1,j=len>>1,k; i<len-1; i++) {            if(i<j) swap(y[i],y[j]);            k=len>>1;            while(j>=k) {                j-=k;                k>>=1;            }            if(j<k) j+=k;        }    }public:    void fft(Complex y[],int len,int on) {        change(y,len);        double tmp=-on*2*acos(-1.0);        for(int h=2; h<=len; h<<=1) {            Complex wn(cos(tmp/h),sin(tmp/h));            for(int j=0; j<len; j+=h) {                Complex w(1,0);                int h2=h>>1;                for(int k=j; k<j+h2; k++) {                    u=y[k];                    t=w*y[k+h2];                    y[k]=u+t;                    y[k+h2]=u-t;                    w=w*wn;                }            }        }        if(on==-1) {            for(int i=0; i<len; i++) {                y[i].x/=len;            }        }    }} g;int flag[M*4];Complex x[M*4];int a[M*2];int main() {    int n,q;    while(~scanf("%d",&n)) {        mt(flag,0);        int maxn = 0;        for(int i=0; i<n; i++) {            scanf("%d",&a[i]);            flag[a[i]] = 1;            maxn = max(maxn,a[i]);        }        int len = 1;        maxn<<=1;        while(len<maxn) len<<=1;        for(int i=0; i<len; i++) {            x[i] = Complex(flag[i],0);        }        g.fft(x,len,1);        for(int i=0;i<len;i++){            x[i] = x[i]*x[i];        }        g.fft(x,len,-1);        mt(flag,0);        for(int i=0;i<n;i++){            flag[a[i]]++;        }        for(int i=0;i<len;i++){            flag[i] += (int)(x[i].x+0.5);        }//        for(int i=0;i<len;i++){//            printf("%d--->%d\n",i,flag[i]);//        }        scanf("%d",&q);        int b;        int ans = 0;        while(q--){            scanf("%d",&b);            if(flag[b]) ans++;        }        printf("%d\n",ans);    }    return 0;}/**31356245789*/


0 0
原创粉丝点击