ACM Hong Kong Online game a question. A+b problem (FFT)

Source: Internet
Author: User





Original title address: Https://open.kattis.com/problems/aplusb



FFT Code Reference Kuangbin's blog: http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html






A+b problem



Given N integers in the range [−50000,50000], how many ways is there to pick three



Integers ai, aJ, aK, such that I, J, K is pairwise distinct and ai+aj=ak? Ways



is different if their ordered triples (i,J,K) of indices are different.



Input



The first line of input consists of a single integer N



(1≤N≤200000). The next line consists of n space-separated integers a1,a2,...,aN



Output



Output An integer representing the number of ways.


Sample Input 1

Sample Output 1

4

1 2 3 4

4




Sample Input 2

Sample Output 2

6

1 1 3 3 4 6

10





Author (s): Tung Kam Chuen



Source: Hong Kong Regional Online Preliminary 2016






Test instructions: To a sequence, choose from three numbers AI, AJ, AK, make Ai+aj=ak, ask how many groups ( I, J, K) meet the conditions.



is actually an FFT.



Note that the data range of a array, a[i] may be negative, all a[i]+50000, negative numbers are converted to positive processing;



If there are 0 in the array, delete the 0 first and the last special deal.



Converts a array into num array, Num[i] indicates the number of occurrences of I.



Then the NUM array and the NUM array are convolution, resulting in a new num array.



num array Meaning: Num[x] Indicates how many kinds of ai+aj=x, (I,J) are made.





#include <algorithm>
#include <cstring>
#include <string.h>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <cstdio>
#include <cmath>

#define LL long long
#define N 200005
#define INF 0x3ffffff

using namespace std;

const double PI = acos (-1.0);


struct Complex // plural
{
    double r, i;
    Complex (double _r = 0, double _i = 0)
    {
        r = _r; i = _i;
    }
    Complex operator + (const Complex & b)
    {
        return Complex (r + b.r, i + b.i);
    }
    Complex operator-(const Complex & b)
    {
        return Complex (r-b.r, i-b.i);
    }
    Complex operator * (const Complex & b)
    {
        return Complex (r * b.r-i * b.i, r * b.i + i * b.r);
    }
};

void change (Complex y [], int len) // Binary Asymmetric Inversion Permutation O (logn)
{
    int i, j, k;
    for (i = 1, j = len / 2; i <len-1; i ++)
    {
        if (i <j) swap (y [i], y [j]);
        k = len / 2;
        while (j> = k)
        {
            j-= k;
            k / = 2;
        }
        if (j <k) j + = k;
    }
}
void fft (Complex y [], int len, int on) // DFT and FFT
{
    change (y, len);
    for (int h = 2; h <= len; h << = 1)
    {
        Complex wn (cos (-on * 2 * PI / h), sin (-on * 2 * PI / h));
        for (int j = 0; j <len; j + = h)
        {
            Complex w (1,0);
            for (int k = j; k <j + h / 2; k ++)
            {
                Complex u = y [k];
                Complex t = w * y [k + h / 2];
                y [k] = u + t;
                y [k + h / 2] = u-t;
                w = w * wn;
            }
        }
    }
    if (on == -1)
        for (int i = 0; i <len; i ++)
            y [i] .r / = len;
}


const int M = 50000; // all elements of a array + M, make a [i]> = 0
const int MAXN = 800040;

Complex x1 [MAXN];
int a [MAXN / 4]; // Original array
long long num [MAXN]; // Array obtained using FFT
long long tt [MAXN]; // Count the number of occurrences of each element of the array

int main ()
{
    int n = 0; // n means the number of array elements except 0
    int tot;
    scanf ("% d", & tot);
    memset (num, 0, sizeof (num));
    memset (tt, 0, sizeof (tt));

    int cnt0 = 0; // cnt0 counts the number of 0
    int aa;

    for (int i = 0; i <tot; i ++)
        {
            scanf ("% d", & aa);
            if (aa == 0) {cnt0 ++; continue;} // Delete all 0 first, and consider 0 in the end
            else a [n] = aa;
            num [a [n] + M] ++;
            tt [a [n] + M] ++;
            n ++;
        }

    sort (a, a + n);
    int len1 = a [n-1] + M + 1;
    int len = 1;

    while (len <2 * len1) len << = 1;

    for (int i = 0; i <len1; i ++) {
         x1 [i] = Complex (num [i], 0);
    }
    for (int i = len1; i <len; i ++) {
         x1 [i] = Complex (0,0);
    }
    fft (x1, len, 1);

    for (int i = 0; i <len; i ++) {
        x1 [i] = x1 [i] * x1 [i];
    }
    fft (x1, len, -1);

    for (int i = 0; i <len; i ++) {
         num [i] = (long long) (x1 [i] .r + 0.5);
    }

    len = 2 * (a [n-1] + M);
        
    for (int i = 0; i <n; i ++) // delete the case of ai + ai
           num [a [i] + a [i] + 2 * M]-;
/ *
   for (int i = 0; i <len; i ++) {
            if (num [i]) cout << i-2 * M << ‘‘ << num [i] << endl;
    }
* /
    long long ret = 0;

    int l = a [n-1] + M;

    for (int i = 0; i <= l; i ++) // Ai, aj, ak are not 0
        {
            if (tt [i]) ret + = (long long) (num [i + M] * tt [i]);
        }

    ret + = (long long) (num [2 * M] * cnt0); // case of ai + aj = 0

    if (cnt0! = 0)
        {
            if (cnt0> = 3) {// Ai, aj, ak are all 0
                long long tmp = 1;
                tmp * = (long long) (cnt0);
                tmp * = (long long) (cnt0-1);
                tmp * = (long long) (cnt0-2);
                ret + = tmp;
            }
             for (int i = 0; i <= l; i ++)
                {
                    if (tt [i]> = 2) {// x + 0 = x case
                        long long tmp = (long long) cnt0;
                        tmp * = (long long) (tt [i]);
                        tmp * = (long long) (tt [i] -1);
                        ret + = tmp * 2;
                    }
                }
        }

    printf ("% lld \ n", ret);

    return 0;
} 





ACM Hong Kong Online game a question. A+b problem (FFT)


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.