zoukankan      html  css  js  c++  java
  • UVALive

    题意:给N个数a[i],再给M个数,问这M个数中有多少满足:出现在N个数中或能表示成某两个数之和.
    分析:FFT求出能够生成的数的系数,给出的M个数若在生成的项中系数不为0,则计数+1

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int MAXN = 4e5 + 10;
    const double PI = acos(-1.0);
    struct Complex{
        double x, y;
        inline Complex operator+(const Complex b) const {
            return (Complex){x +b.x,y + b.y};
        }
        inline Complex operator-(const Complex b) const {
            return (Complex){x -b.x,y - b.y};
        }
        inline Complex operator*(const Complex b) const {
            return (Complex){x *b.x -y * b.y,x * b.y + y * b.x};
        }
    } va[MAXN * 2 + MAXN / 2], vb[MAXN * 2 + MAXN / 2];
    int lenth = 1, rev[MAXN * 2 + MAXN / 2];
    int N, M;   // f 和 g 的数量
        //f g和 的系数
        // 卷积结果
        // 大数乘积
    int f[MAXN],g[MAXN];
    vector<LL> conv;
    vector<LL> multi;
    //f g
    void init()
    {
        int tim = 0;
        lenth = 1;
        conv.clear(), multi.clear();
        memset(va, 0, sizeof va);
        memset(vb, 0, sizeof vb);
        while (lenth <= N + M - 2)
            lenth <<= 1, tim++;
        for (int i = 0; i < lenth; i++)
            rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (tim - 1));
    }
    void FFT(Complex *A, const int fla)
    {
        for (int i = 0; i < lenth; i++){
            if (i < rev[i]){
                swap(A[i], A[rev[i]]);
            }
        }
        for (int i = 1; i < lenth; i <<= 1){
            const Complex w = (Complex){cos(PI / i), fla * sin(PI / i)};
            for (int j = 0; j < lenth; j += (i << 1)){
                Complex K = (Complex){1, 0};
                for (int k = 0; k < i; k++, K = K * w){
                    const Complex x = A[j + k], y = K * A[j + k + i];
                    A[j + k] = x + y;
                    A[j + k + i] = x - y;
                }
            }
        }
    }
    void getConv()
    {
        init();
        for (int i = 0; i < N; i++)
            va[i].x = f[i];
        for (int i = 0; i < M; i++)
            vb[i].x = g[i];
        FFT(va, 1), FFT(vb, 1);
        for (int i = 0; i < lenth; i++)
            va[i] = va[i] * vb[i];
        FFT(va, -1);
        for (int i = 0; i <= N + M - 2; i++)
            conv.push_back((LL)(va[i].x / lenth + 0.5));
    }
    
    void getMulti()
    {
        getConv();
        multi = conv;
        reverse(multi.begin(), multi.end());
        multi.push_back(0);
        int sz = multi.size();
        for (int i = 0; i < sz - 1; i++){
            multi[i + 1] += multi[i] / 10;
            multi[i] %= 10;
        }
        while (!multi.back() && multi.size() > 1)
            multi.pop_back();
        reverse(multi.begin(), multi.end());
    }
    
    int a[MAXN];
    int cnt[MAXN];
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int n; int m;
        while(scanf("%d",&n)==1){
            int mx = 0;
            memset(cnt,0,sizeof(cnt));
            for(int i=1;i<=n;++i){
                scanf("%d",&a[i]);
                cnt[a[i]]=1;
                mx = max(mx,a[i]);
            }
            for(int i=0;i<=mx;++i){
                f[i] = g[i] = cnt[i];
            }
            N = M = mx+1;
            getConv();
            scanf("%d",&m);
            int sum;
            LL res=0;
            for(int i=1;i<=m;++i){
                scanf("%d",&sum);
                if(sum<=mx*2 && (conv[sum]|| cnt[sum]))
                    res++;
            }
            printf("%lld
    ",res);
        }
        return 0;
    }
    
    为了更好的明天
  • 相关阅读:
    linux内核中GNU C和标准C的区别
    linux内核中GNU C和标准C的区别
    Getting start with dbus in systemd (02)
    Getting start with dbus in systemd (01)
    Getting start with dbus in systemd (03)
    物理内存相关的三个数据结构
    数据类型对应字节数(32位,64位 int 占字节数)
    Linux kernel 内存
    共模电感的原理以及使用情况
    [原创]DC-DC输出端加电压会烧毁
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9707612.html
Copyright © 2011-2022 走看看