链接
题解
FFT
代码
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef complex<double> C;
ll read(ll x=0)
{
ll c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return f*x;
}
ll a[maxn], b[maxn], c[maxn], sa[maxn], sb[maxn], s[maxn], n=100000, N;
struct FFT
{
int n, R[maxn];
typedef complex<double> C;
C a[maxn], b[maxn];
const double pi=acos(-1);
void init(int bound) //bound是积多项式的最高次幂
{
int L(0);
for(n=1;n<=bound;n<<=1,L++);
for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1)),a[i]=b[i]=0;
}
void fft(C* a, int opt)
{
int i, j, k;
C wn, w, x, y;
for(i=0;i<n;i++)if(i>R[i])swap(a[i],a[R[i]]);
for(i=1;i<n;i<<=1)
{
wn=C(cos(pi/i),opt*sin(pi/i));
for(j=0;j<n;j+=i<<1)
for(w=C(1,0),k=0;k<i;k++,w=w*wn)
{
x=a[k+j], y=a[k+j+i]*w;
a[k+j]=x+y, a[k+j+i]=x-y;
}
}
if(opt==-1)for(i=0;i<n;i++)a[i]/=n;
}
void run()
{
fft(a,1), fft(b,1);
for(int i=0;i<n;i++)a[i]*=b[i];
fft(a,-1);
}
}fft;
ll abc(ll* a, ll *b, ll *c)
{
ll i, ans=0, s1=0, s2=0;
fft.init(2*n);
rep(i,n)fft.a[i]=C(a[i]);
rep(i,n)fft.b[i]=C(b[i]);
fft.run();
for(i=n;i;i--)sa[i]=sa[i+1]+a[i];
for(i=n;i;i--)sb[i]=sb[i+1]+b[i];
for(i=2*n;i;i--)s[i]=s[i+1]+ll(fft.a[i].real()+0.5);
rep(i,n)
{
ll t=s[i];
t -= sa[i]*sb[1];
t -= sb[i]*sa[1];
t += sa[i]*sb[i];
ans += c[i]*t;
}
return ans;
}
ll abb(ll *a, ll *b, ll *c)
{
ll i, j, ans=0;
rep(i,n)sa[i]=sa[i-1]+a[i];
rep(i,n)ans+=b[i]*c[i]*sa[i-1];
return ans;
}
ll aaa(ll *a, ll *b, ll *c)
{
ll i, ans=0;
rep(i,n)ans+=a[i]*b[i]*c[i];
return ans;
}
int main()
{
ll i, j, k, T=read(), ans=0, kase=0;
while(T--)
{
N=read();
rep(i,n)a[i]=b[i]=c[i]=0;
ans=0;
if(N<=1000)
{
rep(i,N)a[i]=read();
rep(i,N)b[i]=read();
rep(i,N)c[read()]++;
rep(i,n)s[i]=s[i-1]+c[i];
for(i=1;i<=N;i++)
{
for(j=1;j<=N;j++)
{
ll smx=a[i]+b[j], smn=max(1ll,abs(a[i]-b[j]));
ans += s[min(n,smx)]-s[smn-1];
}
}
}
else
{
rep(i,N)a[read()]++;
rep(i,N)b[read()]++;
rep(i,N)c[read()]++;
ans=0;
ans+=abc(a,b,c);
ans+=abc(a,c,b);
ans+=abc(b,c,a);
ans+=abb(a,b,c);
ans+=abb(b,a,c);
ans+=abb(c,a,b);
ans+=aaa(a,b,c);
}
printf("Case #%lld: %lld\n",++kase,ans);
}
return 0;
}