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

传送门: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}

设多项式

UVALive_6886_Golf Bot(FFT快速傅里叶变换)_第1张图片

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

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


代码;

#include
#include
#include
#include
#include

#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>1;
            while(j>=k) {
                j-=k;
                k>>=1;
            }
            if(j>1;
                for(int k=j; k%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;
}
/**
3
1
3
5
6
2
4
5
7
8
9
*/


你可能感兴趣的:(ACM,acm,HDU,数论)