https://open.kattis.com/problems/aplusb
Given N integers in the range [−50000,50000], how many ways are there to pick three integers ai, aj, ak, such that i, j, k are pairwise distinct and ai+aj=ak? Two ways are 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
题目大意:给
n
n
n个范围在
[
−
50000
,
50000
]
[-50000,50000]
[−50000,50000]的数,让你求满足
a
i
+
a
j
=
a
k
a_i+a_j=a_k
ai+aj=ak的三元组
(
i
,
j
,
k
)
(i,j,k)
(i,j,k)的数目,且
i
、
j
、
k
i、j、k
i、j、k互不相同。
思路:
F
F
T
FFT
FFT,个人感觉很难的一道题orz……看了半天题解才看懂。
题解:https://blog.csdn.net/Floraqiu/article/details/86611210
#include<bits/stdc++.h>
using namespace std; //FFT模板
typedef long long ll;
const int maxn=1e5+5;
struct Complex
{
double x,y;
Complex(double dx=0,double dy=0)
{
x=dx;
y=dy;
}
};
Complex operator +(Complex a,Complex b)
{
return Complex(a.x+b.x,a.y+b.y);
}
Complex operator -(Complex a,Complex b)
{
return Complex(a.x-b.x,a.y-b.y);
}
Complex operator *(Complex a,Complex b)
{
return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
const double pi=acos(-1.0); //PI
int limit=1,bit=0;
int wz[maxn<<2];
Complex a[maxn<<2];
int v[maxn<<2],cnt[maxn<<2];
ll num[maxn<<2];
void FFT(Complex *A,int inv)
{
for(int i=0;i<limit;i++)
if(i<wz[i])
swap(A[i],A[wz[i]]);
for(int mid=1;mid<limit;mid<<=1)
{
Complex wn(cos(pi/mid),inv*sin(pi/mid));
for(int i=0;i<limit;i+=mid<<1)
{
Complex w(1,0);
for(int j=0;j<mid;j++,w=w*wn)
{
Complex t1=A[i+j];
Complex t2=w*A[i+mid+j];
A[i+j]=t1+t2;
A[i+mid+j]=t1-t2;
}
}
}
}
int main()
{
int n,zero=0;
while(~scanf("%d",&n))
{
memset(wz,0,sizeof(wz));
memset(a,0,sizeof(a));
memset(cnt,0,sizeof(cnt));
memset(num,0,sizeof(num));
limit=1,bit=0;
int len=-1;
for(int i=0;i<n;i++)
{
scanf("%d",&v[i]);
cnt[v[i]+50000]++;
len=max(len,v[i]+50000);
if(v[i]==0)
++zero;
}
int tmp=len;
len<<=1;
while(limit<=len)
{
limit<<=1;
bit++;
}
for(int i=0;i<limit;i++) //从低位到高位
{
if(i<=tmp)
a[i].x=cnt[i];
else
a[i].x=0;
}
for(int i=0;i<limit;i++)
wz[i]=(wz[i>>1]>>1)|((i&1)<<(bit-1));
FFT(a,1);
for(int i=0;i<limit;i++)
a[i]=a[i]*a[i];
FFT(a,-1);
for(int i=0;i<limit;i++)
num[i]=(ll)(a[i].x/limit+0.5);
for(int i=0;i<n;i++)
num[(v[i]+50000)*2]--;
ll ans=0;
for(int i=0;i<n;i++)
{
ans+=num[v[i]+100000];
ans-=2*zero;
if(v[i]==0)
ans+=2;
}
printf("%lld\n",ans);
}
return 0;
}